shu-c-view
Version:
rollup 打包vue组件库框架
490 lines (488 loc) • 12.7 kB
JavaScript
// @ts-nocheck
/**
* Select 选择器
*/
import _get from 'lodash/get';
import _isNil from 'lodash/isNil';
import _set from 'lodash/set';
import _isEqual from 'lodash/isEqual';
import _isEmpty from 'lodash/isEmpty';
import _assign from 'lodash/assign';
import _has from 'lodash/has';
import _isArray from 'lodash/isArray';
import _clone from 'lodash/clone';
import _map from 'lodash/map';
import _find from 'lodash/find';
import { devConsole } from '../helper/util.js';
const BaseSelect = {
name: 'BaseSelect',
inheritAttrs: false,
model: {
prop: 'value',
event: 'selectChange'
},
props: {
value: {
type: [String, Number, Array, Boolean],
required: true
},
api: {
type: String,
default: ''
},
queryParams: {
type: Object,
default() {
return {};
}
},
// 第一次载入时是否自动刷新列表数据
isReloadGrid: {
type: Boolean,
default: true
},
options: {
type: Array
},
// isWidthAdapt: true,宽度则使用auto
width: {
type: String,
default: 'auto'
},
ctStyle: {
type: Object,
default() {
return {};
}
},
ctCls: {
type: Object,
default() {
return {};
}
},
loadFilter: {
type: Function,
default: null
},
displayField: {
type: String,
default: 'name'
},
valueField: {
type: String,
default: 'id'
},
slotNode: {
type: Object,
default: () => {}
},
isRender: {
type: Boolean,
default: true
},
isDisplay: {
type: Boolean,
default: true
},
listeners: {
type: Object,
default: () => {}
},
// 前缀的单位
preUnit: {
type: String,
default: ''
},
// 后缀的单位
sufUnit: {
type: String,
default: ''
},
// 是否选中第一个,单选时起效
isSelectedFirstRow: {
type: Boolean,
default: false
},
// 动态宽度-单选时生效,设置后 width 参数将失效
isWidthAdapt: {
type: Boolean,
default: false
}
},
data() {
this.vQueryParams = _isEmpty(this.api) ? {} : _assign({}, this.queryParams);
this.events = {
onLoadSuccess: 'onLoadSuccess'
};
// this.vValue = this.$attrs.multiple ? _assign([], this.value) : this.value;
return {
vValue: this.$attrs.multiple ? _assign([], this.value) : this.value,
vOptions: []
};
},
computed: {
elOptions() {
const elOptions = [];
const h = this.$createElement;
if (this.options) {
this.vOptions = this.options;
}
if (_isNil(this.vOptions)) {
return;
}
for (let i = 0; i < this.vOptions.length; i++) {
const option = this.vOptions[i];
if (_has(this.$scopedSlots, 'default')) {
elOptions.push(
h(
'el-option',
{
props: {
key: option[this.valueField],
label:
this.preUnit + option[this.displayField] + this.sufUnit,
value: option[this.valueField],
disabled: option.disabled
}
},
[
h('template', { slot: 'default' }, [
/* this.$scopedSlots.default({
[this.displayField]: option[this.displayField],
[this.valueField]: option[this.valueField]
}) */
this.$scopedSlots.default(_clone(option))
])
]
)
);
} else {
elOptions.push(
h('el-option', {
props: {
key: option[this.valueField],
label: this.preUnit + option[this.displayField] + this.sufUnit,
value: option[this.valueField],
disabled: option.disabled
}
})
);
}
}
/* const elOptions = this.vOptions.map(option => {
return this.$createElement('el-option', {
props: {
key: option[this.valueField],
label: option[this.displayField],
value: option[this.valueField],
disabled: option.disabled
}
})
}) */
return elOptions;
},
optionLabel() {
const option = this.vOptions.find(
item => item[this.valueField] === this.vValue
);
return _get(option, this.displayField);
},
slotElement() {
const nodes = [];
const multiple = _get(this.$attrs, 'multiple', false);
if (this.isWidthAdapt && !multiple) {
nodes.push(
this.$createElement('template', { slot: 'prefix' }, [
this.optionLabel
])
);
}
if (!this.isWidthAdapt && _has(this.$slots, 'prefix')) {
nodes.push(
this.$createElement('template', { slot: 'prefix' }, [
this.$slots.prefix
])
);
}
// if (_has(this.$slots, 'empty')) {
// nodes.push(
// this.$createElement('template', { slot: 'empty' }, [
// this.$slots.empty
// ])
// );
// }
// }
return nodes;
}
},
watch: {
value(value, oldValue) {
if (!_isEqual(value, oldValue) && !_isEqual(this.vValue, value)) {
this.vValue = value;
// this._changeEvent(this.vValue);
// this._selectChangeEvent(this.vValue);
}
},
api: {
handler() {
this.isReloadGrid && this._fetchList();
},
immediate: true
},
options: {
handler() {
if (!_isEmpty(this.options) && this.api.length === 0) {
if (
this.isSelectedFirstRow &&
(!_has(this.$attrs, 'multiple') || this.$attrs.multiple === false)
) {
this.vValue = _get(this.options, `[0].${this.valueField}`);
setTimeout(() => {
this._selectChangeEvent(this.vValue);
}, 0);
}
}
},
deep: true,
immediate: true
}
},
methods: {
/**
* @desc 获取远程服务器数据的操作
* @method
*/
_fetchList() {
if (_isEmpty(this.api) || _isNil(this.$api)) {
return;
}
this.$api[this.api](this.vQueryParams)
.then(resData => {
if (!_isNil(this.loadFilter)) {
resData = this.loadFilter(resData.data);
}
if (
this.isSelectedFirstRow &&
!_isEmpty(resData.data) &&
(!_has(this.$attrs, 'multiple') || this.$attrs.multiple === false)
) {
this.vValue = _get(resData, `data[0].${this.valueField}`);
setTimeout(() => {
this._selectChangeEvent(this.vValue);
}, 0);
}
setTimeout(() => {
this.$emit(this.events.onLoadSuccess, resData.data);
}, 0);
this.vOptions = resData.data;
return true;
})
.catch(error => {
console.error(error);
});
},
/**
* @desc 选中值发生变化时触发
* @event FastComboBox#_changeEvent
* @param {Array} value - 选中项
*/
_changeEvent(value) {
const v = this.multiple ? _assign([], value) : value;
if (
_isEqual(_isNil(this.listeners), false) &&
_has(this.listeners, 'change')
) {
this.listeners.change(v);
return;
}
this.$emit('change', v);
},
/**
* @desc 下拉框出现/隐藏时触发
* @event FastComboBox#_visibleChangeEvent
* @param {boolean} value
*/
_visibleChangeEvent(value) {
if (
_isEqual(_isNil(this.listeners), false) &&
_has(this.listeners, 'visible-change')
) {
this.listeners['visible-change'](value);
return;
}
this.$emit('visible-change', value);
},
/**
* @desc 多选模式下移除tag时触发
* @event FastComboBox#_removeTag
* @param {*} value
*/
_removeTag(value) {
if (
_isEqual(_isNil(this.listeners), false) &&
_has(this.listeners, 'remove-tag')
) {
this.listeners['remove-tag'](value);
return;
}
this.$emit('remove-tag', value);
},
/**
* @desc 可清空的单选模式下用户点击清空按钮时触发
* @event FastComboBox#_clearEvent
*/
_clearEvent() {
if (
_isEqual(_isNil(this.listeners), false) &&
_has(this.listeners, 'clear')
) {
this.listeners.clear();
return;
}
this.$emit('clear');
},
/**
* @desc 当 input 失去焦点时触发
* @event FastComboBox#_blurEvent
* @param {*} event
*/
_blurEvent(event) {
if (
_isEqual(_isNil(this.listeners), false) &&
_has(this.listeners, 'blur')
) {
this.listeners.blur(event);
return;
}
this.$emit('blur', event);
},
/**
* @desc 当 input 获得焦点时触发
* @event FastComboBox#_focusEvent
* @param {*} event
*/
_focusEvent(event) {
if (
_isEqual(_isNil(this.listeners), false) &&
_has(this.listeners, 'focus')
) {
this.listeners.focus(event);
return;
}
this.$emit('focus', event);
},
/**
* @desc 下拉选择项发生改变时
* @event FastInput#_selectChangeEvent
* @param {Array} value - 选中项
*/
_selectChangeEvent(value) {
const v = this.multiple ? _assign([], value) : value;
if (
_isEqual(_isNil(this.listeners), false) &&
_has(this.listeners, 'selectChange')
) {
this.listeners.selectChange(v);
return;
}
// v-model
this.$emit('selectChange', v);
},
/**
* @desc 手动执行刷新数据操作
* @method
* @param {Object} params - 查询条件
*/
reload(params = {}) {
if (!_isEmpty(this.api)) {
_assign(this.vQueryParams, params);
this._fetchList();
}
},
getOptions() {
return _map(this.vOptions, p => {
return { ...p };
});
},
getChangedOption() {
if (_has(this.$attrs, 'multiple') && this.$attrs.multiple) {
// 多选
return _map(this.vValue, v => {
return { ..._find(this.vOptions, o => o[this.valueField] === v) };
});
}
// 单选
const option = _find(
this.vOptions,
item => item[this.valueField] === this.vValue
);
if (option) {
return { ...option };
}
}
},
render(h) {
// v-if
if (_isEqual(this.isRender, false)) {
return h();
}
const style = _assign({}, _get(this.$props, 'ctStyle', {})); // { ..._get(this.$props, 'ctStyle', {}) }
if (this.width !== 'auto' && !this.isWidthAdapt) {
style.width = this.width;
}
// v-show
if (_isEqual(this.isDisplay, false)) {
_set(style, 'display', 'none');
}
return h(
'el-select',
{
ref: 'el-select-ref',
class: _assign(
{
'base-select': true,
select__autoWidth: this.isWidthAdapt && this.optionLabel
},
_get(this.$props, 'ctCls', {})
),
style,
attrs: {
id: this.$attrs.id
},
props: _assign({}, this.$attrs, { value: this.vValue }), // { ...this.$attrs, value: this.vValue },
on: {
change: this._changeEvent,
'visible-change': this._visibleChangeEvent,
'remove-tag': this._removeTag,
clear: this._clearEvent,
blur: this._blurEvent,
focus: this._focusEvent,
input: val => {
// v-model
this.vValue = val;
this._selectChangeEvent(this.vValue);
}
}
},
[
this.elOptions,
this.slotElement,
h('template', { slot: 'empty' }, [this.$slots.empty])
]
);
}
};
BaseSelect.install = function(Vue, ElComponents) {
// 用于按需加载的时候独立使用
devConsole(`按需加载独立组件:${BaseSelect.name}`);
if (_isArray(ElComponents) && !_isEmpty(ElComponents)) {
for (let i = 0; i < ElComponents.length; i++) {
if (ElComponents[i].name !== BaseSelect.name) {
Vue.use(ElComponents[i]);
}
}
}
Vue.component(BaseSelect.name, BaseSelect);
};
export { BaseSelect };