You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
10 KiB
315 lines
10 KiB
3 years ago
|
import classNames from './classNames'
|
||
|
import eventsMixin from './eventsMixin'
|
||
|
|
||
|
const DEFAULT_TRIGGER = 'onClick'
|
||
|
const CELL_NAME = '../cell/index'
|
||
|
const FIELD_NAME = '../field/index'
|
||
|
|
||
|
const defaultToolbar = {
|
||
|
title: '请选择',
|
||
|
cancelText: '取消',
|
||
|
confirmText: '确定',
|
||
|
}
|
||
|
|
||
|
const defaultEvents = {
|
||
|
onChange() {},
|
||
|
onConfirm() {},
|
||
|
onCancel() {},
|
||
|
onVisibleChange() {},
|
||
|
onValueChange() {},
|
||
|
}
|
||
|
|
||
|
const defaultPlatformProps = {
|
||
|
labelPropName: 'label',
|
||
|
format(values, props) {
|
||
|
return Array.isArray(values.displayValue) ? values.displayValue.join(',') : values.displayValue
|
||
|
},
|
||
|
}
|
||
|
|
||
|
const defaultFieldNames = {
|
||
|
label: 'label',
|
||
|
value: 'value',
|
||
|
children: 'children',
|
||
|
}
|
||
|
|
||
|
export default function popupMixin(selector = '#wux-picker', platformProps = defaultPlatformProps) {
|
||
|
return Behavior({
|
||
|
behaviors: [eventsMixin({ defaultEvents })],
|
||
|
properties: {
|
||
|
toolbar: {
|
||
|
type: Object,
|
||
|
value: defaultToolbar,
|
||
|
},
|
||
|
trigger: {
|
||
|
type: String,
|
||
|
value: DEFAULT_TRIGGER,
|
||
|
},
|
||
|
defaultVisible: {
|
||
|
type: Boolean,
|
||
|
value: false,
|
||
|
},
|
||
|
visible: {
|
||
|
type: Boolean,
|
||
|
value: false,
|
||
|
},
|
||
|
controlled: {
|
||
|
type: Boolean,
|
||
|
value: false,
|
||
|
},
|
||
|
disabled: {
|
||
|
type: Boolean,
|
||
|
value: false,
|
||
|
},
|
||
|
},
|
||
|
data: {
|
||
|
mounted: false,
|
||
|
popupVisible: false,
|
||
|
inputValue: [],
|
||
|
},
|
||
|
methods: {
|
||
|
/**
|
||
|
* 设置组件显示或隐藏
|
||
|
*/
|
||
|
setVisibleState(popupVisible, callback = () => {}) {
|
||
|
if (this.data.popupVisible !== popupVisible) {
|
||
|
const params = {
|
||
|
mounted: true,
|
||
|
inputValue: this.data.value, // forceUpdate
|
||
|
popupVisible,
|
||
|
}
|
||
|
this.setData(popupVisible ? params : { popupVisible }, () => {
|
||
|
// collect field component & forceUpdate
|
||
|
if (popupVisible && this.hasFieldDecorator) {
|
||
|
const field = this.getFieldElem()
|
||
|
if (field) {
|
||
|
field.changeValue(field.data.value)
|
||
|
}
|
||
|
}
|
||
|
callback()
|
||
|
})
|
||
|
}
|
||
|
},
|
||
|
/**
|
||
|
* 触发 visibleChange 事件
|
||
|
*/
|
||
|
fireVisibleChange(popupVisible) {
|
||
|
if (this.data.popupVisible !== popupVisible) {
|
||
|
if (!this.data.controlled) {
|
||
|
this.setVisibleState(popupVisible)
|
||
|
}
|
||
|
this.setScrollValue(undefined)
|
||
|
this.triggerEvent('visibleChange', { visible: popupVisible })
|
||
|
}
|
||
|
},
|
||
|
/**
|
||
|
* 打开
|
||
|
*/
|
||
|
open() {
|
||
|
this.fireVisibleChange(true)
|
||
|
},
|
||
|
/**
|
||
|
* 关闭
|
||
|
*/
|
||
|
close(callback) {
|
||
|
if (typeof callback === 'function') {
|
||
|
const values = this.getPickerValue(this.scrollValue || this.data.inputValue)
|
||
|
callback.call(this, this.formatPickerValue(values))
|
||
|
}
|
||
|
this.fireVisibleChange(false)
|
||
|
},
|
||
|
/**
|
||
|
* 组件关闭时重置其内部数据
|
||
|
*/
|
||
|
onClosed() {
|
||
|
this.picker = null
|
||
|
this.setData({ mounted: false, inputValue: null })
|
||
|
},
|
||
|
/**
|
||
|
* 点击确定按钮时的回调函数
|
||
|
*/
|
||
|
onConfirm() {
|
||
|
this.close((values) => {
|
||
|
this.triggerEvent('change', values) // collect field component
|
||
|
this.triggerEvent('confirm', values)
|
||
|
})
|
||
|
},
|
||
|
/**
|
||
|
* 点击取消按钮时的回调函数
|
||
|
*/
|
||
|
onCancel() {
|
||
|
this.close((values) => this.triggerEvent('cancel', values))
|
||
|
},
|
||
|
/**
|
||
|
* 每列数据选择变化后的回调函数
|
||
|
*/
|
||
|
onValueChange(e) {
|
||
|
if (!this.data.mounted) return
|
||
|
const { value } = e.detail
|
||
|
if (this.data.cascade) {
|
||
|
this.setCasecadeScrollValue(value)
|
||
|
} else {
|
||
|
this.setScrollValue(value)
|
||
|
}
|
||
|
|
||
|
this.updated(value, true)
|
||
|
this.triggerEvent('valueChange', this.formatPickerValue(e.detail))
|
||
|
},
|
||
|
/**
|
||
|
* 获取当前 picker 的值
|
||
|
*/
|
||
|
getPickerValue(value = this.data.inputValue) {
|
||
|
this.picker = this.picker || this.selectComponent(selector)
|
||
|
return this.picker && this.picker.getValue(value)
|
||
|
},
|
||
|
/**
|
||
|
* 格式化 picker 返回值
|
||
|
*/
|
||
|
formatPickerValue(values) {
|
||
|
return {
|
||
|
...values,
|
||
|
[platformProps.labelPropName]: platformProps.format(values, this.data),
|
||
|
}
|
||
|
},
|
||
|
/**
|
||
|
* 获取 field 父元素
|
||
|
*/
|
||
|
getFieldElem() {
|
||
|
return this.field = (this.field || this.getRelationNodes(FIELD_NAME)[0])
|
||
|
},
|
||
|
/**
|
||
|
* 设置子元素 props
|
||
|
*/
|
||
|
setChildProps() {
|
||
|
if (this.data.disabled) return
|
||
|
const elements = this.getRelationNodes(CELL_NAME)
|
||
|
const { trigger = DEFAULT_TRIGGER } = this.data
|
||
|
if (elements.length > 0) {
|
||
|
elements.forEach((inputElem) => {
|
||
|
const { inputEvents } = inputElem.data
|
||
|
const oriInputEvents = inputElem.data.oriInputEvents || { ...inputEvents }
|
||
|
inputEvents[trigger] = (...args) => {
|
||
|
if (oriInputEvents && oriInputEvents[trigger]) {
|
||
|
oriInputEvents[trigger](...args)
|
||
|
}
|
||
|
this.onTriggerClick()
|
||
|
}
|
||
|
inputElem.setData({ oriInputEvents, inputEvents })
|
||
|
})
|
||
|
}
|
||
|
},
|
||
|
/**
|
||
|
* 触发事件
|
||
|
*/
|
||
|
onTriggerClick() {
|
||
|
this.fireVisibleChange(!this.data.popupVisible)
|
||
|
},
|
||
|
/**
|
||
|
* 阻止移动触摸
|
||
|
*/
|
||
|
noop() {},
|
||
|
/**
|
||
|
* 更新值
|
||
|
*/
|
||
|
updated(inputValue, isForce) {
|
||
|
if (!this.hasFieldDecorator || isForce) {
|
||
|
if (this.data.inputValue !== inputValue) {
|
||
|
this.setData({ inputValue })
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
/**
|
||
|
* 记录每列数据的变化值
|
||
|
*/
|
||
|
setScrollValue(value) {
|
||
|
this.scrollValue = value
|
||
|
},
|
||
|
/**
|
||
|
* 记录每列数据的变化值 - 针对于级联
|
||
|
*/
|
||
|
setCasecadeScrollValue(value) {
|
||
|
if (value && this.scrollValue) {
|
||
|
const length = this.scrollValue.length
|
||
|
if (length === value.length && this.scrollValue[length - 1] === value[length - 1]) {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
this.setScrollValue(value)
|
||
|
},
|
||
|
},
|
||
|
lifetimes: {
|
||
|
ready() {
|
||
|
const { defaultVisible, visible, controlled, value } = this.data
|
||
|
const popupVisible = controlled ? visible : defaultVisible
|
||
|
|
||
|
// 若 defaultFieldNames 存在,则缓存之,并传递给子组件,只生效一次
|
||
|
if ('defaultFieldNames' in this.data) {
|
||
|
this.setData({
|
||
|
fieldNames: Object.assign({}, defaultFieldNames, this.data.defaultFieldNames),
|
||
|
})
|
||
|
}
|
||
|
|
||
|
this.mounted = true
|
||
|
this.scrollValue = undefined
|
||
|
this.setVisibleState(popupVisible)
|
||
|
this.setChildProps()
|
||
|
},
|
||
|
detached() {
|
||
|
this.mounted = false
|
||
|
},
|
||
|
},
|
||
|
definitionFilter(defFields) {
|
||
|
// set default child
|
||
|
Object.assign(defFields.relations = (defFields.relations || {}), {
|
||
|
[CELL_NAME]: {
|
||
|
type: 'child',
|
||
|
observer() {
|
||
|
this.setChildProps()
|
||
|
},
|
||
|
},
|
||
|
[FIELD_NAME]: {
|
||
|
type: 'ancestor',
|
||
|
},
|
||
|
})
|
||
|
|
||
|
// set default classes
|
||
|
Object.assign(defFields.computed = (defFields.computed || {}), {
|
||
|
classes: ['prefixCls', function(prefixCls) {
|
||
|
const wrap = classNames(prefixCls)
|
||
|
const toolbar = `${prefixCls}__toolbar`
|
||
|
const inner = `${prefixCls}__inner`
|
||
|
const cancel = classNames(`${prefixCls}__button`, {
|
||
|
[`${prefixCls}__button--cancel`]: true,
|
||
|
})
|
||
|
const confirm = classNames(`${prefixCls}__button`, {
|
||
|
[`${prefixCls}__button--confirm`]: true,
|
||
|
})
|
||
|
const hover = `${prefixCls}__button--hover`
|
||
|
const title = `${prefixCls}__title`
|
||
|
|
||
|
return {
|
||
|
wrap,
|
||
|
toolbar,
|
||
|
inner,
|
||
|
cancel,
|
||
|
confirm,
|
||
|
hover,
|
||
|
title,
|
||
|
}
|
||
|
}],
|
||
|
})
|
||
|
|
||
|
// set default observers
|
||
|
Object.assign(defFields.observers = (defFields.observers || {}), {
|
||
|
visible(popupVisible) {
|
||
|
if (this.data.controlled) {
|
||
|
this.setVisibleState(popupVisible)
|
||
|
}
|
||
|
},
|
||
|
value(value) {
|
||
|
this.updated(value)
|
||
|
},
|
||
|
})
|
||
|
},
|
||
|
})
|
||
|
}
|