榆山数据端小程序
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.
 
 

155 lines
5.5 KiB

import baseComponent from '../helpers/baseComponent'
import classNames from '../helpers/classNames'
import arrayTreeFilter from '../helpers/arrayTreeFilter'
import { defaultFieldNames, props } from '../multi-picker-view/props'
baseComponent({
properties: {
...props,
cols: {
type: Number,
value: 3,
},
},
data: {
inputValue: [],
showOptions: [],
fieldNames: defaultFieldNames,
},
observers: {
inputValue(newVal) {
this.fixFieldName()
// HACK: 去掉不必要的属性,防止数据溢出
const value = this.getFieldName('value')
const label = this.getFieldName('label')
const showOptions = this.getShowOptions(newVal).reduce((acc, option) => (
[...acc, option.map((v) => ({ [value]: v[value], [label]: v[label], disabled: !!v.disabled }))]
), [])
this.setData({ showOptions })
},
['value, options, cols'](value, options, cols) {
this.fixFieldName()
this.setValue(value, options, cols)
},
},
methods: {
updated(inputValue) {
if (this.data.inputValue !== inputValue) {
this.setData({
inputValue,
})
}
},
setValue(value, options, cols) {
const inputValue = this.getRealValue(options, value, cols)
this.updated(inputValue)
},
onValueChange(e) {
const { value, index } = e.detail
const newValue = this.getNextValue(value, index)
const inputValue = this.getRealValue(this.data.options, newValue)
const values = this.getValue(inputValue)
// forceUpdate picker
this.updated(inputValue)
this.triggerEvent('valueChange', { ...values, index })
},
getValue(value = this.data.inputValue) {
const newValue = this.getRealValue(this.data.options, value)
const newShowOptions = this.getShowOptions(newValue)
this.picker = this.picker || this.selectComponent('#wux-picker')
return this.picker.getValue(newValue, newShowOptions)
},
getNextValue(activeValue, index) {
const { options } = this.data
const value = this.getFieldName('value')
const childrenKeyName = this.getFieldName('children')
const children = arrayTreeFilter(options, (option, level) => level <= index && option[value] === activeValue[level], { childrenKeyName })
let data = children[index]
let i = index + 1
while (i < this.data.cols) {
if (data && data[childrenKeyName] && data[childrenKeyName].length) {
data = data[childrenKeyName][0]
activeValue[i] = data[value]
}
i++
}
activeValue.length = i
return activeValue
},
getRealValue(options, activeValue, cols = this.data.cols) {
if (!activeValue || !activeValue.length || activeValue.indexOf(undefined) > -1 || activeValue.length !== cols) {
const value = this.getFieldName('value')
const childrenKeyName = this.getFieldName('children')
let newValue = []
let data = [...options]
let i = 0
while (i < cols) {
if (data && data.length) {
newValue[i] = activeValue[i] || data[0][value]
let index = 0
if (newValue[i]) {
index = data.map((v) => v[value]).indexOf(newValue[i])
if (index === -1) {
index = 0
newValue[i] = data[0][value]
}
}
data = data[index][childrenKeyName]
}
i++
}
return newValue
}
return activeValue
},
getActiveOptions(activeValue) {
const { options } = this.data
const value = this.getFieldName('value')
const childrenKeyName = this.getFieldName('children')
return arrayTreeFilter(options, (option, level) => option[value] === activeValue[level], { childrenKeyName })
},
getShowOptions(activeValue) {
const { options, cols } = this.data
const children = this.getFieldName('children')
const result = this.getActiveOptions(activeValue).map((activeOption) => activeOption[children]).filter((activeOption) => !!activeOption)
return [options, ...result].filter((_, i) => i < cols)
},
getFieldName(name) {
return this.data.fieldNames[name]
},
/**
* Allways set fieldNames
* Because `observers` always takes precedence over `attached` on first mount
* HACK: https://github.com/wux-weapp/wux-weapp/issues/352
*/
fixFieldName() {
if (!this.hasFieldName) {
const fieldNames = Object.assign({}, defaultFieldNames, this.data.defaultFieldNames)
this.setData({ fieldNames })
this.hasFieldName = true
}
},
},
attached() {
const { value, options, cols } = this.data
this.fixFieldName()
this.setValue(value, options, cols)
},
})