纸通宝小程序
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.
 

264 lines
8.1 KiB

import baseComponent from '../helpers/baseComponent'
import classNames from '../helpers/classNames'
import arrayTreeFilter from '../helpers/arrayTreeFilter'
const WUX_CASCADER = 'wux-cascader'
const defaultFieldNames = {
label: 'label',
value: 'value',
children: 'children',
}
baseComponent({
externalClasses: ['wux-scroll-view-class'],
properties: {
prefixCls: {
type: String,
value: 'wux-cascader',
},
value: {
type: Array,
value: []
},
title: {
type: String,
value: '',
},
options: {
type: Array,
value: []
},
chooseTitle: {
type: String,
value: '请选择',
},
visible: {
type: Boolean,
value: false,
},
defaultFieldNames: {
type: Object,
value: defaultFieldNames,
},
},
data: {
activeOptions: [],
activeIndex: 0,
bodyStyle: '',
activeValue: [],
intoValue: ['ViewId_00000', 'ViewId_00000', 'ViewId_00000'], // 新增的用于scroll-view的指示修改
showOptions: [],
fieldNames: {}
},
computed: {
classes: ['prefixCls', function(prefixCls) {
const wrap = classNames(prefixCls)
const hd = `${prefixCls}__hd`
const title = `${prefixCls}__title`
const menus = `${prefixCls}__menus`
const menu = `${prefixCls}__menu`
const bd = `${prefixCls}__bd`
const inner = `${prefixCls}__inner`
const scrollView = `${prefixCls}__scroll-view`
const option = `${prefixCls}__option`
const item = `${prefixCls}__item`
const icon = `${prefixCls}__icon`
const ft = `${prefixCls}__ft`
return {
wrap,
hd,
title,
menus,
menu,
bd,
inner,
scrollView,
option,
item,
icon,
ft,
}
}],
},
observers: {
options() {
this.getCurrentOptions(this.data.activeValue, false)
}
},
methods: {
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 } = this.data
const children = this.getFieldName('children')
const result = this.getActiveOptions(activeValue).map((activeOption) => activeOption[children]).filter((activeOption) => !!activeOption)
return [options, ...result]
},
getMenus(activeValue = [], hasChildren) {
const { options, chooseTitle } = this.data
const activeOptions = this.getActiveOptions(activeValue)
if (hasChildren) {
const value = this.getFieldName('value')
const label = this.getFieldName('label')
activeOptions.push({ [value]: WUX_CASCADER, [label]: chooseTitle })
}
return activeOptions
},
getNextActiveValue(value, optionIndex) {
let { activeValue } = this.data
activeValue = activeValue.slice(0, optionIndex + 1)
activeValue[optionIndex] = value
return activeValue
},
updated: function(currentOptions, optionIndex, condition, callback, flag) {
const value = this.getFieldName('value')
const children = this.getFieldName('children')
const hasChildren = currentOptions[children] && currentOptions[children].length > 0
const activeValue = this.getNextActiveValue(currentOptions[value], optionIndex)
const activeOptions = this.getMenus(activeValue, hasChildren)
const activeIndex = activeOptions.length - 1
const showOptions = this.getShowOptions(activeValue)
const params = { activeValue, activeOptions, activeIndex, showOptions }
// 判断 hasChildren 计算需要更新的数据
if (hasChildren || (activeValue.length === showOptions.length && (optionIndex = Math.max(0, optionIndex - 1)))) {
params.bodyStyle = `transform: translate(${-50 * optionIndex}%)`
params.showOptions = showOptions
}
// 判断是否需要 setData 更新数据
if (condition) {
if(flag){
this.triggerEvent('init', activeOptions)
}
this.setData(params)
}
// 回调函数
if (typeof callback === 'function') {
callback.call(this, currentOptions, activeOptions, !hasChildren)
}
},
/**
* 更新级联数据
* @param {Array} activeValue 当前选中值
*/
getCurrentOptions(activeValue = this.data.activeValue, flag) {
const optionIndex = Math.max(0, activeValue.length - 1)
const activeOptions = this.getActiveOptions(activeValue)
const currentOptions = activeOptions[optionIndex]
if (currentOptions) {
this.updated(currentOptions, optionIndex, true, null, flag)
} else {
const value = this.getFieldName('value')
const label = this.getFieldName('label')
activeOptions.push({ [value]: WUX_CASCADER, [label]: this.data.chooseTitle })
const showOptions = this.getShowOptions(activeValue)
const activeIndex = activeOptions.length - 1
const params = { showOptions, activeOptions, activeIndex, bodyStyle: ''}
this.setData(params)
}
},
/**
* 点击菜单时的回调函数
*/
onMenuClick(e) {
const { menuIndex } = e.currentTarget.dataset
const index = menuIndex > 1 ? menuIndex - 1 : 0
const bodyStyle = `transform: translate(${-50 * index}%)`
this.setData({ bodyStyle, activeIndex: menuIndex})
},
/**
* 点击选项时的回调函数
*/
onItemSelect(e) {
const { item, optionIndex } = e.currentTarget.dataset
// 判断是否禁用
if (!item || item.disabled) return
this.setData({ intoValue: ['ViewId_00000', 'ViewId_00000', 'ViewId_00000']})
// 更新新数据
this.updated(item, optionIndex, true, this.onChange, false)
const activeLength = this.data.activeValue.length
// 更新intoValue的下一级数据,选择项的下一级列表scroll-top
if(activeLength < this.data.intoValue.length && activeLength < this.data.showOptions.length){
if(this.data.showOptions[activeLength][0]){
this.setData({
['intoValue[' + activeLength + ']']: 'ViewId_' + this.data.showOptions[activeLength][0].value
})
}
}
},
/**
* 组件关闭时的回调函数
*/
onPopupClose(val) {
this.setData({ visible: false })
this.triggerEvent('close', val)
},
onPopupShow(){
let { intoValue } = this.data
for (let i = 0; i < this.data.activeValue.length; i++) {
intoValue[i] = 'ViewId_' + this.data.activeValue[i]
}
this.setData({ intoValue })
},
/**
* 选择完成时的回调函数
*/
onChange(currentOptions = {}, activeOptions = [], done = false) {
const options = activeOptions.filter((n) => n[this.getFieldName('value')] !== WUX_CASCADER)
const value = options.map((n) => n[this.getFieldName('value')])
// 判断是否异步加载
if (currentOptions.isLeaf === false && !currentOptions.children) {
this.emitEvent({ value, options, done: false })
this.triggerEvent('load', { value, options })
return
}
// 正常加载
this.emitEvent({ value, options, done })
},
emitEvent(params = {}) {
this.triggerEvent('change', params)
// 当选择完成时关闭组件
if (params.done) {
this.setData({ value: params.value })
this.onPopupClose(params)
}
},
getFieldName(name) {
return this.data.fieldNames[name]
},
showPicker(region){
this.setData({ activeValue: region, visible: true })
this.getCurrentOptions(region, false)
}
},
attached() {
const { value } = this.data
var activeValue = value
if (!activeValue || activeValue.length == 0){
activeValue = ["440000", "", ""]
}
const fieldNames = Object.assign({}, defaultFieldNames, this.data.defaultFieldNames)
this.setData({ activeValue, fieldNames }, () => this.getCurrentOptions(activeValue, false))
}
})