shu-c-view
Version:
rollup 打包vue组件库框架
1,356 lines (1,353 loc) • 49.5 kB
JavaScript
/**
* @desc select-tree 选择器
*/
import _assign from 'lodash/assign';
import _includes from 'lodash/includes';
import _findIndex from 'lodash/findIndex';
import _isNil from 'lodash/isNil';
import _toNumber from 'lodash/toNumber';
import _isEmpty from 'lodash/isEmpty';
import _has from 'lodash/has';
import _omit from 'lodash/omit';
import _isArray from 'lodash/isArray';
import _isEqual from 'lodash/isEqual';
import _difference from 'lodash/difference';
import _filter from 'lodash/filter';
import _map from 'lodash/map';
import _get from 'lodash/get';
import _isString from 'lodash/isString';
import _find from 'lodash/find';
import _forEach from 'lodash/forEach';
import { devConsole } from '../helper/util.js';
const BaseSelectTree = {
name: 'BaseSelectTree',
inheritAttrs: false,
model: {
prop: 'selectTreeValue',
event: 'selectTreeChange'
},
props: {
// 传入默认选中值 ['',''] String 需要默认选中时请结合 'defaultCheckedKeys' 参数
// 值的匹配必须和 'defaultCheckedKeys'相同
/* value: {
default() {
return [];
}
}, */
// 最多只能选择几个数量
maxItem: {
type: Number
},
// 最多只能选择几个数量-对象形配置
maxItemObj: {
type: Object
// default() {
// return { level: 1, max: 3 }; // 第一层最多选中3个节点,第一层下面的节点仍旧可以选中,其余第一层节点下的节点无法选中
// }
},
// 输入框宽度
width: {
type: [Number, String],
default: 160
},
// tree面板宽度
treeWidth: {
type: Number,
default: 200
},
// Select 组件头部内容
prefixLabel: {
type: String
},
// 是否多选
multiple: {
type: Boolean,
default: false
},
// 默认要勾选tree的节点keys 必须是唯一值id的value
// 适用于数据源由外部传入和lazy为false,如果是懒加载 lazy: true 远程获取必须在数据中增加'check'字段标明是否选中
defaultCheckedKeys: {
type: Array,
default() {
return [];
}
},
// 定义外部 v-model 值,默认值 null 因为单选传入 String ,多选 array 并不确定
selectTreeValue: {
default() {
return null;
}
},
// 自定义样式名
ctCls: {
type: String
},
// 下拉面板的扩展样式
popoverClass: {
type: String
},
// 外部事件扩展 只有 'change' 选中值发生改变事件
listeners: {
type: Object,
default() {
return {};
}
},
// 显示字段
displayField: {
type: String,
default: 'name'
},
// 值字段
valueField: {
type: String,
default: 'id'
},
// 是否显示完整的路径(true 显示完整的路径,false 仅显示最后一级)
showAllLevels: {
type: Boolean,
default: false
},
// 是否显示搜索框
isRenderSearchInput: {
type: Boolean,
default: false
},
// 自定义过滤函数
filterNodeMethodHandle: {
type: Function
},
// 是否显示下拉树选中的值到select的框中
isShowCheckSelectValue: {
type: Boolean,
default: true
},
// 父子级联如果是false的情况下,是否需要父子联动(选中一个子节点级联选中对应的所有父级节点,取消某个父节点级联取消该节点下的所有子节点)
checkStrictlyFalseCancelChildChecked: {
type: Boolean,
default: false
},
// 动态宽度-单选时生效,设置后 width 参数将失效
isWidthAdapt: {
type: Boolean,
default: false
}
},
watch: {
selectTreeValue(val) {
if (_isNil(this.originalSelectTreeValue)) {
this.originalSelectTreeValue = val; // 首次记录原始值
}
if (_isNil(val) || val.length === 0) {
this.clear();
} else {
const checkedKeys = this.$refs[this.treeUserRef]
.getTree()
.getCheckedKeys();
if (_isArray(val) && this.multiple && !_isEqual(val, checkedKeys)) {
if (val.length < checkedKeys.length) {
// 多选
const aDifferenceList = _difference(checkedKeys, val); // 删除了哪几个值
const bDifferenceList = _difference(val, checkedKeys); // 添加哪几个值
this.outValueRemove(aDifferenceList);
this.outValueAdd(bDifferenceList);
this.$refs[this.treeUserRef].setCheckedKeys(
this.curSelectValueList
);
} else {
const aDifferenceList = _difference(val, checkedKeys); // 添加哪几个值
const bDifferenceList = _difference(checkedKeys, val); // 去除哪几个值
this.outValueAdd(aDifferenceList);
_forEach(aDifferenceList, aDiff => {
this.getTree()
.getTree()
.setChecked(aDiff, true);
});
_forEach(bDifferenceList, bDiff => {
this.getTree()
.getTree()
.setChecked(bDiff, false);
});
}
return;
}
// 单选
if (!_isNil(val) && val !== this.curSelectValue) {
this.setSingleNode();
}
}
}
},
data() {
this.popoverOffsetTop = 0; // 下拉面板的 offsetTop 偏差值
this.selectInputHeight = 0; // select 控件对应的 input 框的高度
this.treeProps = {};
this.originalSelectTreeValue = null;
return {
placement: 'bottom-start',
treeUserRef: 'selectTree',
popoverVisible: false,
// 本地数据
curSelectNodeList: [],
curSelectLabelList: [],
curSelectValueList: [], // 复选
curSelectNode: null,
curSelectLabel: '', // 单选
curSelectValue: '',
curDefaultCheckedKeys: [...this.defaultCheckedKeys],
treeValue: [],
options: [], // [{ value: '', label: '' }]
filterText: ''
};
},
computed: {
optionLabel() {
const option = _find(this.options, option => {
return option[this.valueField] === this.curSelectValue;
});
return _get(option, this.displayField);
},
prefixLabelVNode() {
let prefixLabelVNode = null;
const h = this.$createElement;
if (this.prefixLabel && !this.isWidthAdapt) {
prefixLabelVNode = [
h('template', { slot: 'prefix' }, [this.prefixLabel])
];
}
if (this.isWidthAdapt && !this.multiple) {
prefixLabelVNode = h('template', { slot: 'prefix' }, [
this.optionLabel
]);
}
return prefixLabelVNode;
}
},
created() {
if (
!_isEmpty(this.selectTreeValue) &&
(this.selectTreeValue !== '' || !_isNil(this.selectTreeValue))
) {
this.originalSelectTreeValue = this.selectTreeValue; // 首次记录原始值
}
if (_has(this.$attrs, 'props')) {
this.treeProps = _assign(this.$attrs.props, {
label: this.displayField,
value: this.valueField
});
} else {
this.treeProps = {
label: this.displayField,
value: this.valueField
};
}
},
methods: {
/**
* @desc 获取 tree 对象
*/
getTree() {
return this.$refs[this.treeUserRef];
},
/**
* @desc 手动打开tree下拉面板
*/
handOpenTree() {
setTimeout(() => {
this.popoverVisible = true;
}, 0);
},
/**
* @desc 手动隐藏tree下拉面板
*/
handCloseTree() {
setTimeout(() => {
this.popoverVisible = false;
}, 0);
},
/**
* @desc 创建 el-popover
*/
createPopover() {
const vNode = [];
const h = this.$createElement;
vNode.push(
h(
'el-popover',
{
ref: 'base-select-tree-popover',
props: {
popperClass: `base-el-popover ${this.popoverClass}`,
placement: this.placement,
// title: '标题',
width: this.treeWidth,
trigger: 'click',
value: this.popoverVisible
// content: 'hello'
},
on: {
input: val => {
this.popoverVisible = val;
}
}
},
[
/* this.isRenderSearchInput
? h('el-input', {
attrs: {
placeholder: '请输入内容',
maxlength: '30',
clearable: true
},
props: { value: this.filterText, showWordLimit: true },
on: {
input: val => {
this.filterText = val;
this.getTree().getTree().filter(val);
}
}
})
: h(), */
this.createTree(),
h(
'div',
{ slot: 'reference', style: { height: '0px' }, ref: 'bbb' },
// 'click 激活'
[]
)
]
)
);
return vNode;
},
/**
* @desc 创建 el-tree 节点
*/
createSelect() {
const h = this.$createElement;
const style = {
width: _isString(this.width) ? this.width : `${this.width}px`
}; // 文本框控件宽度
if (this.isWidthAdapt) {
style.width = 'auto';
}
let value = [];
if (!this.isShowCheckSelectValue) {
value = [];
}
if (this.multiple) {
value = this.curSelectValueList;
} else {
value = this.curSelectValue;
}
const vNode = h(
'el-select',
{
ref: 'base-select-tree-ref',
// key: `${this._uid}-base-select-tree-ref`,
style,
attrs: {
id: this.$attrs.id,
autofocus: this.$attrs.autofocus,
placeholder: this.$attrs.placeholder
},
class: {
'select-tree__autoWidth': this.isWidthAdapt && this.optionLabel
},
props: _assign(
{},
{
// eslint-disable-next-line no-nested-ternary
/* value: !this.isShowCheckSelectValue
? []
: this.multiple
? this.curSelectValueList
: this.curSelectValue, */
value,
// value: this.multiple
// ? this.curSelectValueList
// : this.curSelectValue,
clearable: true, // 有清除按钮
multiple: this.multiple, // 设置多选,value对应为数组
'collapse-tags': true, // 合并多选
'popper-class': 'base-select-tree__popper'
},
this.$attrs
),
on: {
'hook:mounted': () => {
this.selectInputHeight = this.$refs[
'base-select-tree-ref'
].$el.offsetHeight; // input 框的高度
},
clear: () => {
this.$emit('clearValue', this.multiple ? [] : '');
this.clear();
this.$refs[this.treeUserRef].clearChecked();
this.$emit('selectTreeChange', this.multiple ? [] : '');
this.change([]);
this.setSelectPanel2InputOffsetTop();
this.$emit('clear', this.multiple ? [] : '');
this.$refs['base-select-tree-popover'].doClose();
},
'remove-tag': tag => {
this.$emit('clearValue', tag);
const index = _findIndex(
this.curSelectValueList,
// eslint-disable-next-line no-shadow
value => value === tag
);
const optionIndex = _findIndex(
this.options,
item => item[this.valueField] === tag
);
const cancelCheckedNodes = [];
if (index !== -1) {
cancelCheckedNodes.push(this.curSelectValueList[index]);
this.curSelectNodeList.splice(index, 1);
this.curSelectLabelList.splice(index, 1);
this.curSelectValueList.splice(index, 1);
}
if (optionIndex !== -1) {
this.options.splice(optionIndex, 1);
}
// this.$nextTick(() => {
// this.$emit('selectTreeChange', this.curSelectValueList);
// this.change(this.curSelectNodeList);
// });
// this.$refs[this.treeUserRef].setCheckedKeys(cancelCheckedNodes);
// this.$nextTick(() => {
if (this.multiple && !_get(this.$attrs, 'check-strictly', true)) {
const treeNode = this.$refs[this.treeUserRef]
.getTree()
.getNode(cancelCheckedNodes[0]);
if (treeNode.parent.checked) {
const valueIndex = _findIndex(
this.curSelectValueList,
v => v === _get(treeNode, `parent.data.${this.valueField}`)
);
if (valueIndex !== -1) {
cancelCheckedNodes.push(
this.curSelectValueList[valueIndex]
);
this.curSelectNodeList.splice(valueIndex, 1);
this.curSelectLabelList.splice(valueIndex, 1);
this.curSelectValueList.splice(valueIndex, 1);
this.options.splice(valueIndex, 1);
}
}
}
// this.$emit('selectTreeChange', this.curSelectValueList);
// this.change(this.curSelectNodeList);
// });
this.$refs[this.treeUserRef].setCheckedKeys(
this.curSelectValueList
);
// this.$refs[this.treeUserRef]
// .getTree()
// .setChecked(cancelCheckedNodes[0], false);
this.setSelectPanel2InputOffsetTop();
// this.$emit('remove-tag', this.multiple ? [] : '');
this.$emit('remove-tag', tag);
// this.$nextTick(() => {
this.$emit('selectTreeChange', [...this.curSelectValueList]);
this.change(this.curSelectNodeList);
// });
}
},
nativeOn: {
click: event => {
const selectTree = this.$refs['base-select-tree-ref'];
if (
!_isNil(selectTree) &&
!_isNil(selectTree.$el) &&
!_isNil(document.body.clientHeight)
) {
if (
document.body.clientHeight -
selectTree.$el.parentNode.offsetTop <
470
) {
this.placement = 'top-start';
}
}
if (
!_has(this.$attrs, 'disabled') ||
(_has(this.$attrs, 'disabled') &&
this.$attrs.disabled === false)
) {
this.$refs['base-select-tree-ref'].blur();
this.$refs.bbb.click(); // 如果是 el-button ,那么自动触发 click 事件 `this.$refs.bbb.$el.click();`
event.stopPropagation();
event.preventDefault();
return false;
}
return true;
}
}
},
[
this.prefixLabelVNode,
this.createOptions(),
h(
'div',
{
class: 'base-select-tree-down-empty',
slot: 'empty',
style: { display: 'none' }
},
[]
)
]
);
return vNode;
},
/**
* @desc 创建 el-option 节点
*/
createOptions() {
const h = this.$createElement;
const vNode = this.options.map(option => {
return h('el-option', {
style: {
/* width: `${this.treeWidth}px`,
height: 'auto',
'max-height': `${this.treeHeight}px`,
'background-color': this.backgroundColor,
padding: '0px',
overflow: 'auto', */
display: 'absolute',
top: '0px',
left: '0px',
height: '0px',
'z-index': '-100'
// display: 'none'
},
props: {
key: option[this.valueField],
label: option[this.displayField],
value: option[this.valueField]
},
on: {
'hook:mounted': () => {}
}
});
});
return vNode;
},
/**
* @desc 创建下拉 tree 控件
*/
createTree() {
const h = this.$createElement;
const that = this;
return h(
'base-tree',
{
/* style: {
height: '100%',
overflow: 'auto',
'font-weight': 'normal'
}, */
// class: 'select-tree-panel',
ref: this.treeUserRef,
attrs: {
defaultCheckedKeys: this.curDefaultCheckedKeys,
checkStrictly: _get(this.$attrs, 'check-strictly', this.multiple), // 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false
showCheckbox: this.multiple, // 出现复选框
'show-checkbox': this.multiple,
..._omit(this.$attrs, [
'defaultCheckedKeys',
'checkStrictly',
'showCheckbox',
'default-checked-keys',
'check-strictly',
'show-checkbox'
]),
'filter-node-method': (value, data) => {
if (!value) {
return true;
}
if (!_isNil(this.filterNodeMethodHandle)) {
return this.filterNodeMethodHandle(value, data);
}
return _get(data, this.displayField).indexOf(value) !== -1;
}
},
props: _assign(
{},
{
// displayField: this.displayField,
// valueField: this.valueField,
// treeValue: this.treeValue, // v-model value 属性
listeners: {
nodeClick: (record, node, tree) => {
// 使 input 失去焦点,并隐藏下拉框
this.$refs['base-select-tree-ref'].blur();
this.$refs['base-select-tree-popover'].doClose();
const eventName = _has(this.$listeners, 'nodeClick')
? 'nodeClick'
: 'node-click';
this.$emit(eventName, record, node, tree);
},
checkChange: (record, checked) => {
if (
this.curSelectValueList.includes(record[this.valueField]) &&
!checked
) {
const index = this.curSelectValueList.findIndex(
value => value === record[this.valueField]
);
const optionIndex = this.options.findIndex(
item => item[this.valueField] === record[this.valueField]
);
if (index !== -1) {
this.curSelectValueList.splice(index, 1);
this.curSelectLabelList.splice(index, 1);
this.curSelectNodeList.splice(index, 1);
}
if (optionIndex !== -1) {
this.options.splice(optionIndex, 1);
}
}
}
}
},
this.$attrs,
{
props: this.treeProps,
nodeKey: this.getNodeKey()
}
),
on: {
// 数据加载完成
afterLoadStore: () => {
// 默认选中
if (!_isNil(that.selectTreeValue)) {
if (that.multiple) {
that.curDefaultCheckedKeys.push(...that.selectTreeValue);
} else {
// that.curDefaultCheckedKeys.push(that.selectTreeValue); // 单选不用设置,因为单选其实没有选中的效果
}
setTimeout(() => {
if (that.multiple) {
const nodes = that.$refs[
that.treeUserRef
].getCheckedNodes();
if (!_isEmpty(nodes)) {
// eslint-disable-next-line no-restricted-syntax
for (let i = 0, len = nodes.length; i < len; i += 1) {
const treeNode = that
.getTree()
.getTree()
.getNode(nodes[i][that.valueField]);
const levelStr = that
.getTree()
.getNodeParentLevel(treeNode);
that.options.push({
[that.valueField]: nodes[i][that.valueField],
[that.displayField]: that.showAllLevels
? levelStr
: nodes[i][that.displayField]
});
if (that.multiple) {
that.curSelectValueList.push(
nodes[i][that.valueField]
);
that.curSelectLabelList.push(
nodes[i][that.displayField]
);
that.curSelectNodeList.push(nodes[i]);
if (
!_get(this.$attrs, 'check-strictly', this.multiple)
) {
// 父子级联
const vValues = that.getCheckedLeafNodes();
this.$emit('selectTreeChange', vValues); // 多选
} else {
const checkedValues = _map(
this.$refs[this.treeUserRef].getCheckedNodes(),
node => {
return _get(node, this.valueField);
}
); // 多选但不是父子级联把勾选的节点都传递出去
this.$emit('selectTreeChange', checkedValues);
}
}
}
if (!that.multiple) {
that.curSelectValue = nodes[0][that.valueField];
}
}
} else {
// 单选
that.setSingleNode();
}
}, 0);
}
setTimeout(() => {
this.$emit('afterLoadStore');
}, 0);
},
check: (node, treeCheckedNode) => {
this.$emit('check', node, treeCheckedNode);
// 多选-点击复选框
// this.$refs.bbb.click(); // 防止下拉树面板在点击后隐藏
this.setSelectPanel2InputOffsetTop();
if (this.multiple) {
const checkedKeys = this.$refs[this.treeUserRef]
.getTree()
.getCheckedKeys();
// 操作最大的选中数量
if (
!_isNil(this.maxItem) &&
checkedKeys.length > this.maxItem
) {
this.$refs[this.treeUserRef]
.getTree()
.setChecked(node[this.valueField], false);
return;
}
if (!_isNil(this.maxItemObj)) {
const treeNode = this.$refs[this.treeUserRef]
.getTree()
.getNode(_get(node, this.valueField));
const level = _get(this.maxItemObj, 'level');
const max = _get(this.maxItemObj, 'max');
const checkedNodes = _map(checkedKeys, v =>
this.$refs[this.treeUserRef].getTree().getNode(v)
);
const levelNodes = _filter(
checkedNodes,
v => v.level === level
);
if (levelNodes.length > max) {
this.$refs[this.treeUserRef]
.getTree()
.setChecked(node[this.valueField], false);
return;
}
if (levelNodes.length === max && treeNode.level > level) {
const isInclude = this.getTree().isTreeNodesIncludeNode(
levelNodes,
treeNode
); // 选中的节点是否在指定大类的小类中,如果是则选中否则取消选中
// 不包含在里面取消当前选中的节点
if (!isInclude) {
this.cancelChecked(node);
return;
}
}
if (treeNode.level > level && levelNodes.length === max) {
const isInclude = this.getTree().isTreeNodesIncludeNode(
levelNodes,
treeNode
); // 选中的节点是否在指定大类的小类中,如果是则选中否则取消选中
// 不包含在里面取消当前选中的节点
if (!isInclude) {
this.cancelChecked(node);
return;
}
}
}
if (!_get(this.$attrs, 'check-strictly', this.multiple)) {
// 多选,父子级联
const options = [];
this.curSelectLabelList = [];
this.curSelectValueList = [];
this.options = [];
this.curSelectNodeList = treeCheckedNode.checkedNodes;
// eslint-disable-next-line no-restricted-syntax
for (
let i = 0, len = this.curSelectNodeList.length;
i < len;
i += 1
) {
const sChildField = _get(
this.treeProps,
'children',
'children'
);
const children = _get(
this.curSelectNodeList[i],
sChildField
);
if (_isNil(children) || _isEmpty(children)) {
const name = _get(
this.curSelectNodeList[i],
this.displayField
);
const value = _get(
this.curSelectNodeList[i],
this.valueField
);
this.curSelectLabelList.push(name);
this.curSelectValueList.push(value);
const treeNode = this.getTree()
.getTree()
.getNode(value);
const levelStr = this.getTree().getNodeParentLevel(
treeNode
);
options.push({
[this.displayField]: this.showAllLevels
? levelStr
: name,
[this.valueField]: value
});
}
}
this.options = options;
} else {
const treeNode = this.getTree()
.getTree()
.getNode(node[this.valueField]);
// 父子不级联
if (
this.checkStrictlyFalseCancelChildChecked &&
!treeNode.checked
) {
// 取消选中
const childCheckNodes = this.getTree().getNodeCheckedChild(
treeNode
);
// eslint-disable-next-line no-restricted-syntax
for (
let i = 0, len = childCheckNodes.length;
i < len;
i += 1
) {
this.getTree()
.getTree()
.setChecked(childCheckNodes[i], false);
const index = _findIndex(
this.curSelectValueList,
v => v === childCheckNodes[i]
);
if (index !== -1) {
this.curSelectNodeList.splice(index, 1);
this.curSelectLabelList.splice(index, 1);
this.curSelectValueList.splice(index, 1);
this.options.splice(index, 1);
}
}
}
if (
this.checkStrictlyFalseCancelChildChecked &&
treeNode.checked
) {
// 级联选中
const parentTreeNodes = this.getTree().getNodeParentNodes(
treeNode
);
const checkedHandle = () => {
// eslint-disable-next-line no-restricted-syntax
for (
let i = 0, len = parentTreeNodes.length;
i < len;
i += 1
) {
// eslint-disable-next-line no-shadow
const node = parentTreeNodes[i];
if (!node.checked) {
// this.$nextTick(() => {
this.$refs[this.treeUserRef]
.getTree()
.setChecked(node.data[this.valueField], true);
if (
!_includes(
this.curSelectValueList,
node.data[this.valueField]
)
) {
this.curSelectNodeList.push(node.data);
this.curSelectLabelList.push(
node.data[this.displayField]
);
this.curSelectValueList.push(
node.data[this.valueField]
);
this.options.push({
[this.displayField]: this.showAllLevels
? this.getTree().getNodeParentLevel(node)
: node.data[this.displayField],
[this.valueField]: node.data[this.valueField]
});
}
// });
}
}
};
checkedHandle();
/* if (_isNil(this.maxItemObj)) {
checkedHandle();
} else {
const level = _get(this.maxItemObj, 'level');
const max = _get(this.maxItemObj, 'max');
const checkedNodes = _map(checkedKeys, v =>
this.$refs[this.treeUserRef].getTree().getNode(v)
);
const levelNodes = _filter(
checkedNodes,
v => v.level === level
);
if (levelNodes.length < max) {
checkedHandle();
}
} */
}
if (!_includes(checkedKeys, node[this.valueField])) {
this.$emit('selectTreeChange', [
...this.curSelectValueList
]);
this.change(this.curSelectNodeList);
return;
}
this.curSelectNodeList.push(node);
this.curSelectLabelList.push(node[this.displayField]);
this.curSelectValueList.push(node[this.valueField]);
const levelStr = this.showAllLevels
? this.getTree().getNodeParentLevel(node)
: node[this.displayField];
this.options.push({
[this.displayField]: levelStr,
[this.valueField]: node[this.valueField]
});
}
this.$emit('selectTreeChange', [...this.curSelectValueList]); // 这里注意需要返回一个新数组,否则我们在操作 this.curSelectValueList 这个数组 push、splice 的元素后会触发 selectTreeValue 的 watch 监听
this.change([...this.curSelectNodeList]);
}
},
// v-model input事件
currentChange: (record = {}, curNode = {}) => {
// 单选
if (!this.multiple) {
if (
(_has(this.$attrs, 'isSelectedLastNode') &&
this.$attrs.isSelectedLastNode) ||
(_has(this.$attrs, 'is-selected-last-node') &&
this.$attrs['is-selected-last-node'])
) {
const treeProps = this.$refs[this.treeUserRef].defaultProps;
// 设置需要选中最里面的节点
if (
_has(record, treeProps.children) &&
!_isNil(_get(record, treeProps.children)) &&
_get(record, treeProps.children).length !== 0
) {
return;
}
}
const isSelectedLevel =
_has(this.$attrs, 'selectedLevel') ||
_has(this.$attrs, 'selected-level');
const selectedLevelVal =
this.$attrs.selectedLevel || this.$attrs['selected-level'];
const isDisabledNodes =
_has(this.$attrs, 'disabledNodes') ||
_has(this.$attrs, 'disabled-nodes');
const disabledNodesVal =
this.$attrs.disabledNodes || this.$attrs['disabled-nodes'];
if (
(isSelectedLevel &&
selectedLevelVal &&
curNode.level !== selectedLevelVal) ||
(isDisabledNodes &&
!_isEmpty(disabledNodesVal) &&
_includes(
disabledNodesVal,
_get(curNode, `data.${this.valueField}`)
))
) {
return;
}
if (
_has(curNode, 'data.disabled') &&
curNode.data.disabled === true
) {
return;
}
const node = this.getTree()
.getTree()
.getNode(record[this.valueField]);
const levelStr = this.getTree().getNodeParentLevel(node);
this.options = [];
this.options.push({
[this.displayField]: this.showAllLevels
? levelStr
: record[this.displayField],
[this.valueField]: record[this.valueField]
});
this.curSelectValue = record[this.valueField];
this.curSelectLabel = record[this.displayField];
this.$emit('selectTreeChange', this.curSelectValue);
this.change({
[this.displayField]: record[this.displayField],
[this.valueField]: record[this.valueField],
..._omit(record, [this.displayField, this.valueField])
});
}
},
// 清空数据事件
clearData: () => {
this.clear();
this.$refs[this.treeUserRef].clearChecked();
this.$emit('selectTreeChange', this.multiple ? [] : '');
this.change([]);
this.setSelectPanel2InputOffsetTop();
this.$emit('clear', this.multiple ? [] : '');
}
},
scopedSlots: _has(this.$scopedSlots, 'default')
? {
default: props => {
return this.$scopedSlots.default(props);
},
handleIconScope: props => {
return _has(this.$scopedSlots, 'handleMenuScope')
? this.$scopedSlots.handleMenuScope(props)
: h();
}
}
: undefined
},
[
this.isRenderSearchInput
? h('el-input', {
slot: 'searchInputSlot',
class: 'select-tree__input',
attrs: {
placeholder: '请输入内容',
maxlength: '30',
clearable: true
},
props: { value: this.filterText, showWordLimit: true },
on: {
input: val => {
this.filterText = val;
this.getTree()
.getTree()
.filter(val);
}
}
})
: h()
]
);
},
getNodeKey() {
return _get(this.$attrs, 'node-key', this.valueField);
},
/**
* @desc 设置单选-选中效果(单选其实在树上面没有选中效果)
*/
setSingleNode() {
const that = this;
if (
!_isNil(that.$refs[that.treeUserRef]) &&
!_isNil(that.$refs[that.treeUserRef].getTree()) &&
!_isNil(that.selectTreeValue)
) {
const elTree = that.$refs[that.treeUserRef].getTree();
const checkedNode = elTree.getNode(that.selectTreeValue);
if (!_isNil(checkedNode)) {
const record = checkedNode;
this.options = [];
this.options.push({
[that.displayField]: this.showAllLevels
? this.getTree().getNodeParentLevel(checkedNode)
: record.data[that.displayField],
[that.valueField]: record.data[that.valueField]
});
that.curSelectValue = record.data[that.valueField];
that.curSelectLabel = record.data[that.displayField];
that.$emit('selectTreeChange', that.curSelectValue);
that.change({
[that.displayField]: record.data[that.displayField],
[that.valueField]: record.data[that.valueField]
});
elTree.setCurrentKey(that.selectTreeValue); // 设置单选选中效果
}
}
},
/**
* @desc 计算下拉面板和input框之间的高度差值
*/
setSelectPanel2InputOffsetTop() {
setTimeout(() => {
const popoverEl = this.$refs['base-select-tree-popover'].$el;
if (!_isNil(popoverEl) && !_isNil(popoverEl.childNodes)) {
const selectInputHeight = this.$refs['base-select-tree-ref'].$el
.clientHeight; // input 框的高度
// console.info('abc ', this.$refs['base-select-tree-ref']);
const oldTopNum = this.$refs[
this.treeUserRef
].$el.parentNode.style.top.replace('px', '');
// console.info(this.selectInputHeight, selectInputHeight);
if (selectInputHeight > this.selectInputHeight) {
const dValue = selectInputHeight - this.selectInputHeight; // 差值
this.$refs[
this.treeUserRef
].$el.parentNode.style.top = `${_toNumber(oldTopNum) +
_toNumber(dValue)}px`;
} else if (selectInputHeight <= this.selectInputHeight) {
const dValue = this.selectInputHeight - selectInputHeight;
// console.info('================', dValue);
if (dValue !== 0) {
this.$refs[
this.treeUserRef
].$el.parentNode.style.top = `${_toNumber(oldTopNum) -
_toNumber(dValue)}px`;
}
}
this.selectInputHeight = selectInputHeight;
}
}, 100);
// console.info('abc ', this.$refs.bbb.offsetTop);
/* console.info(this.$refs[this.treeUserRef].$el.parentNode.style.top.replace('px', ''));
console.info('33333333 ', this.$refs['base-select-tree-popover'].$el.childNodes[0].offsetTop);
console.info('4444 ', this.$refs[this.treeUserRef].$el.parentNode); */
},
/**
* @desc 清空
*/
clear() {
if (!_isEmpty(this.curSelectNodeList)) {
this.curSelectNodeList = [];
this.curSelectLabelList = [];
this.curSelectValueList = [];
this.curSelectNode = null;
this.curSelectLabel = '';
this.curSelectValue = '';
this.curDefaultCheckedKeys = [...this.defaultCheckedKeys];
this.treeValue = [];
this.options = [];
const baseTree = this.$refs[this.treeUserRef].getTree();
if (!_isEmpty(baseTree.getCheckedKeys())) {
if (this.multiple) {
baseTree.setCheckedKeys([]);
} else {
baseTree.setCurrentKey(null);
}
}
}
if (
!this.multiple &&
(this.selectTreeValue === '' || _isNil(this.selectTreeValue))
) {
this.curSelectNode = null;
this.curSelectLabel = '';
this.curSelectValue = '';
const baseTree = this.$refs[this.treeUserRef].getTree();
if (!_isNil(baseTree.getCurrentKey())) {
baseTree.setCurrentKey(null);
}
}
},
/**
* @desc 重置
*/
reset() {
this.clear();
this.$nextTick(() => {
// 默认勾选的节点的 key 的数组
if (
!_isEmpty(this.defaultCheckedKeys) ||
!_isEmpty(this.originalSelectTreeValue)
) {
const checkedNodeKeys = [...this.defaultCheckedKeys];
if (this.multiple) {
checkedNodeKeys.push(...this.originalSelectTreeValue);
} else {
checkedNodeKeys.push(this.originalSelectTreeValue);
}
if (!_isEmpty(checkedNodeKeys)) {
const baseTree = this.$refs[this.treeUserRef].getTree();
baseTree.setCheckedKeys(checkedNodeKeys);
const nodes = this.$refs[this.treeUserRef].getCheckedNodes();
const childFieldName = _get(this.treeProps, 'children', 'children');
_forEach(nodes, node => {
if (
!_has(node, childFieldName) ||
_isNil(node[childFieldName]) ||
_isEmpty(node[childFieldName])
) {
this.curSelectNodeList.push(node);
this.curSelectLabelList.push(node[this.displayField]);
this.curSelectValueList.push(node[this.valueField]);
const levelStr = this.showAllLevels
? this.getTree().getNodeParentLevel(node)
: node[this.displayField];
this.options.push({
[this.displayField]: levelStr,
[this.valueField]: node[this.valueField]
});
}
});
}
if (this.multiple) {
const checkedNodes = this.getCheckedLeafNodes();
this.$emit('selectTreeChange', checkedNodes);
} else {
this.$emit('selectTreeChange', this.originalSelectTreeValue);
}
}
});
},
// 通过 key 设置某个节点的勾选状态,使用此方法必须设置 node-key 属性
setChecked(nodeId, checked = true) {
const nodeIdIndex = _findIndex(
this.curSelectValueList,
curSelectValueItem => curSelectValueItem === nodeId
);
if (nodeIdIndex !== -1) {
this.$refs[this.treeUserRef].getTree().setChecked(nodeId, checked); // 取消选中
this.curSelectValueList.splice(nodeIdIndex, 1);
this.curSelectLabelList.splice(nodeIdIndex, 1);
this.curSelectNodeList.splice(nodeIdIndex, 1);
this.$emit('selectTreeChange', this.curSelectValueList);
}
},
getOptions() {
return JSON.parse(JSON.stringify(this.options));
},
// 获取所有选中的子节点-多选情况下起效
getCheckedLeafNodes(
{ field } = { field: _get(this.$attrs, 'node-key', this.valueField) }
) {
if (this.multiple) {
const nodes = this.$refs[this.treeUserRef].getCheckedNodes();
const childFieldName = _get(this.treeProps, 'children', 'children');
const leafNodeKeys = [];
_forEach(nodes, node => {
if (
!_has(node, childFieldName) ||
_isNil(node[childFieldName]) ||
_isEmpty(node[childFieldName])
) {
leafNodeKeys.push(_get(node, field));
}
});
return leafNodeKeys;
}
return '';
},
// 获取所有选中的节点
getCheckedNodes() {
const nodes = this.$refs[this.treeUserRef].getCheckedNodes();
return _map(nodes, node => {
return { ...node };
});
},
// 获取base-select-tree组件当前是打开还是关闭状态
getSelectShowPopper() {
const { showPopper } = this.$refs['base-select-tree-popover'];
return showPopper;
},
/**
* @desc 外部 v-model 直接操作值
*/
outValueRemove(aDifferenceList) {
_forEach(aDifferenceList, aDifferenceVal => {
const index = _findIndex(
this.curSelectValueList,
v => v === aDifferenceVal
);
if (index !== -1) {
this.curSelectValueList.splice(index, 1);
this.curSelectLabelList.splice(index, 1);
this.curSelectNodeList.splice(index, 1);
this.options.splice(index, 1);
}
});
},
/**
* @desc 外部 v-model 直接操作值
*/
outValueAdd(aDifferenceList) {
_forEach(aDifferenceList, aDifferenceVal => {
const treeNode = this.getTree()
.getTree()
.getNode(aDifferenceVal);
if (!_isNil(treeNode)) {
const data = _get(treeNode, 'data', {});
this.curSelectNodeList.push(data);
this.curSelectLabelList.push(data[this.displayField]);
this.curSelectValueList.push(data[this.valueField]);
const levelStr = this.getTree().getNodeParentLevel(treeNode);
this.options.push({
[this.valueField]: data[this.valueField],
[this.displayField]: this.showAllLevels
? levelStr
: data[this.displayField]
});
}
});
},
/**
* @desc 自定义change事件
* @param {Array|String} val
*/
change(val) {
if ('change' in this.listeners) {
this.listeners.change(val);
}
},
/**
* @desc 某个树节点(data对象)取消选中
*/
cancelChecked(treeNodeData) {
this.$refs[this.treeUserRef]
.getTree()
.setChecked(treeNodeData[this.valueField], false);
const index = _findIndex(
this.curSelectValueList,
v => v === treeNodeData[this.valueField]
);
if (index !== -1) {
this.curSelectNodeList.splice(index, 1);
this.curSelectLabelList.splice(index, 1);
this.curSelectValueList.splice(index, 1);
this.options.splice(index, 1);
}
},
// 手动关闭下拉框
doClose() {
const popoverRef = this.$refs['base-select-tree-popover'];
if (!_isNil(popoverRef) && popoverRef.showPopper) {
this.$refs['base-select-tree-ref'].blur();
popoverRef.doClose();
}
}
},
render(h) {
const styleWidth = {};
if (this.isWidthAdapt) {
styleWidth.width = 'auto';
} else {
styleWidth.width = _isString(this.width) ? this.width : `${this.width}px`;
}
return h(
'div',
{
ref: 'base-select-panel',
style: styleWidth,
class: { 'base-select-tree': true, [this.ctCls]: this.ctCls }
},
[this.createSelect(), this.createPopover()]
);
}
};
BaseSelectTree.install = function(Vue, ElComponents) {
// 用于按需加载的时候独立使用
devConsole(`按需加载独立组件:${BaseSelectTree.name}`);
if (_isArray(ElComponents) && !_isEmpty(ElComponents)) {
for (let i = 0; i < ElComponents.length; i++) {
if (ElComponents[i].name !== BaseSelectTree.name) {
Vue.use(ElComponents[i]);
}
}
}
Vue.component(BaseSelectTree.name, BaseSelectTree);
};
export { BaseSelectTree };