对比新文件 |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <my-picker :picker-list="singleColumnPickerList" @confirm="confirm('singleColumn', $event)"> |
| | | <button class="button" type="primary">单列</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.singleColumn.picked"> |
| | | <h4>单列picker选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.singleColumn.picked, null, 4)"></pre> |
| | | </view> |
| | | |
| | | <my-picker |
| | | :picker-list="multiColumnsPickerList" |
| | | column-num="3" |
| | | @change="changeMultiColumns" |
| | | @confirm="confirm('multiColumns', $event)"> |
| | | <button class="button" type="primary">3列联动</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.multiColumns.picked"> |
| | | <h4>3列联动选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.multiColumns.picked, null, 4)"></pre> |
| | | </view> |
| | | <view class="picked-result" v-else-if="demos.multiColumns.columnPicked"> |
| | | <h4>多列联动第{{demos.multiColumns.columnPickedIndex + 1}}列更新:</h4> |
| | | <pre v-html="JSON.stringify(demos.multiColumns.columnPicked, null, 4)"></pre> |
| | | </view> |
| | | |
| | | <my-picker |
| | | column-num="3" |
| | | :picker-list="multiColumnsWithCustomKeyPickerList" |
| | | :picker-style="pickerStyle" |
| | | :picker-key="{value: 'id', label: 'title', children: 'sub'}" |
| | | :before-set-column="addPickerItem" |
| | | :default-value="[2,21,212]" |
| | | :item-rotate-deg="20" |
| | | @change="changeCustomMultiColumns" |
| | | @confirm="confirm('customMultiColumns', $event)"> |
| | | <button class="button" type="primary">完整自定义参数联动</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.customMultiColumns.picked"> |
| | | <h4>完整自定义参数联动选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.customMultiColumns.picked, null, 4)"></pre> |
| | | </view> |
| | | <view class="picked-result" v-else-if="demos.customMultiColumns.columnPicked"> |
| | | <h4>完整自定义参数联动第{{demos.customMultiColumns.columnPickedIndex + 1}}列更新:</h4> |
| | | <pre v-html="JSON.stringify(demos.customMultiColumns.columnPicked, null, 4)"></pre> |
| | | </view> |
| | | |
| | | <my-picker |
| | | :picker-list="multiColumnsPickerList" |
| | | @confirm="confirm('dynamicColumns', $event)"> |
| | | <button class="button" type="primary">非固定列联动</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.dynamicColumns.picked"> |
| | | <h4>非固定列联动选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.dynamicColumns.picked, null, 4)"></pre> |
| | | </view> |
| | | |
| | | <my-picker |
| | | :picker-list="independentMultiColumnsPickerList" |
| | | @confirm="confirm('independentMultiColumns', $event)"> |
| | | <button class="button" type="primary">多列非联动</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.independentMultiColumns.picked"> |
| | | <h4>多列非联动选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.independentMultiColumns.picked, null, 4)"></pre> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import MyPicker from './Picker'; |
| | | |
| | | export default { |
| | | components: {MyPicker}, |
| | | data() { |
| | | return { |
| | | demos: { |
| | | singleColumn: { |
| | | picked: null, |
| | | }, |
| | | multiColumns: { |
| | | picked: null, |
| | | columnPicked: null, |
| | | columnPickedIndex: null, |
| | | }, |
| | | customMultiColumns: { |
| | | picked: null, |
| | | columnPicked: null, |
| | | columnPickedIndex: null, |
| | | }, |
| | | dynamicColumns: { |
| | | picked: null, |
| | | columnPicked: null, |
| | | columnPickedIndex: null, |
| | | }, |
| | | independentMultiColumns: { |
| | | picked: null, |
| | | columnPicked: null, |
| | | }, |
| | | }, |
| | | pickerStyle: { |
| | | cancel: { |
| | | color: '#999', |
| | | 'font-size': '32rpx' |
| | | }, |
| | | confirm: { |
| | | color: 'green', |
| | | 'font-size': '32rpx' |
| | | }, |
| | | column: [ |
| | | {flex: 1}, |
| | | {flex: 1}, |
| | | {flex: 2}, |
| | | ] |
| | | }, |
| | | singleColumnPickerList: [ |
| | | {label: '选项1', value: 1}, |
| | | {label: '选项2', value: 2}, |
| | | {label: '选项3', value: 3}, |
| | | {label: '选项4', value: 4}, |
| | | {label: '选项5', value: 5}, |
| | | {label: '选项6', value: 6}, |
| | | {label: '选项7', value: 7}, |
| | | {label: '选项8', value: 8}, |
| | | {label: '选项9', value: 9}, |
| | | ], |
| | | multiColumnsPickerList: [ |
| | | { |
| | | label: '选项1', |
| | | value: 1, |
| | | children: [ |
| | | { |
| | | label: '选项11', |
| | | value: 11, |
| | | children: [ |
| | | {label: '选项111', value: 111}, |
| | | {label: '选项112', value: 112}, |
| | | {label: '选项113', value: 113}, |
| | | {label: '选项114', value: 114}, |
| | | {label: '选项115', value: 115}, |
| | | ] |
| | | }, |
| | | { |
| | | label: '选项12', |
| | | value: 12, |
| | | children: [ |
| | | {label: '选项121', value: 121}, |
| | | {label: '选项122', value: 122}, |
| | | {label: '选项123', value: 123}, |
| | | {label: '选项124', value: 124}, |
| | | {label: '选项125', value: 125}, |
| | | ] |
| | | }, |
| | | {label: '选项13', value: 13}, |
| | | {label: '选项14', value: 14}, |
| | | {label: '选项15', value: 15}, |
| | | ] |
| | | }, |
| | | { |
| | | label: '选项2', |
| | | value: 2, |
| | | children: [ |
| | | { |
| | | label: '选项21', |
| | | value: 21, |
| | | children: [ |
| | | {label: '选项211', value: 211}, |
| | | {label: '选项212', value: 212}, |
| | | {label: '选项213', value: 213}, |
| | | {label: '选项214', value: 214}, |
| | | {label: '选项215', value: 215}, |
| | | ] |
| | | }, |
| | | { |
| | | label: '选项22', |
| | | value: 22, |
| | | children: [ |
| | | {label: '选项221', value: 221}, |
| | | {label: '选项222', value: 222}, |
| | | {label: '选项223', value: 223}, |
| | | {label: '选项224', value: 224}, |
| | | {label: '选项225', value: 225}, |
| | | ] |
| | | }, |
| | | {label: '选项23', value: 23}, |
| | | {label: '选项24', value: 24}, |
| | | {label: '选项25', value: 25}, |
| | | ] |
| | | }, |
| | | {label: '选项3', value: 3}, |
| | | {label: '选项4', value: 4}, |
| | | {label: '选项5', value: 5}, |
| | | {label: '选项6', value: 6}, |
| | | {label: '选项7', value: 7}, |
| | | {label: '选项8', value: 8}, |
| | | {label: '选项9', value: 9}, |
| | | ], |
| | | multiColumnsWithCustomKeyPickerList: [ |
| | | { |
| | | title: '选项1', |
| | | id: 1, |
| | | sub: [ |
| | | { |
| | | title: '选项11', |
| | | id: 11, |
| | | sub: [ |
| | | {title: '选项111', id: 111}, |
| | | {title: '选项112', id: 112}, |
| | | {title: '选项113', id: 113}, |
| | | {title: '选项114', id: 114}, |
| | | {title: '选项115', id: 115}, |
| | | ] |
| | | }, |
| | | { |
| | | title: '选项12', |
| | | id: 12, |
| | | sub: [ |
| | | {title: '选项121', id: 121}, |
| | | {title: '选项122', id: 122}, |
| | | {title: '选项123', id: 123}, |
| | | {title: '选项124', id: 124}, |
| | | {title: '选项125', id: 125}, |
| | | ] |
| | | }, |
| | | {title: '选项13', id: 13}, |
| | | {title: '选项14', id: 14}, |
| | | {title: '选项15', id: 15}, |
| | | ] |
| | | }, |
| | | { |
| | | title: '选项2', |
| | | id: 2, |
| | | sub: [ |
| | | { |
| | | title: '选项21', |
| | | id: 21, |
| | | sub: [ |
| | | {title: '选项211', id: 211}, |
| | | {title: '选项212', id: 212}, |
| | | {title: '选项213', id: 213}, |
| | | {title: '选项214', id: 214}, |
| | | {title: '选项215', id: 215}, |
| | | ] |
| | | }, |
| | | { |
| | | title: '选项22', |
| | | id: 22, |
| | | sub: [ |
| | | {title: '选项221', id: 221}, |
| | | {title: '选项222', id: 222}, |
| | | {title: '选项223', id: 223}, |
| | | {title: '选项224', id: 224}, |
| | | {title: '选项225', id: 225}, |
| | | ] |
| | | }, |
| | | {title: '选项23', id: 23}, |
| | | {title: '选项24', id: 24}, |
| | | {title: '选项25', id: 25}, |
| | | ] |
| | | }, |
| | | {title: '选项3', id: 3}, |
| | | {title: '选项4', id: 4}, |
| | | {title: '选项5', id: 5}, |
| | | {title: '选项6', id: 6}, |
| | | {title: '选项7', id: 7}, |
| | | {title: '选项8', id: 8}, |
| | | {title: '选项9', id: 9}, |
| | | ], |
| | | independentMultiColumnsPickerList: [ |
| | | [ |
| | | {label: '选项1', value: 1}, |
| | | {label: '选项2', value: 2}, |
| | | {label: '选项3', value: 3}, |
| | | {label: '选项4', value: 4}, |
| | | {label: '选项5', value: 5}, |
| | | {label: '选项6', value: 6}, |
| | | {label: '选项7', value: 7}, |
| | | {label: '选项8', value: 8}, |
| | | {label: '选项9', value: 9}, |
| | | ], |
| | | [ |
| | | {label: '选项1', value: 1}, |
| | | {label: '选项2', value: 2}, |
| | | {label: '选项3', value: 3}, |
| | | {label: '选项4', value: 4}, |
| | | {label: '选项5', value: 5}, |
| | | {label: '选项6', value: 6}, |
| | | {label: '选项7', value: 7}, |
| | | {label: '选项8', value: 8}, |
| | | {label: '选项9', value: 9}, |
| | | ], |
| | | ] |
| | | } |
| | | }, |
| | | methods: { |
| | | confirm(type, picked) { |
| | | this.demos[type].picked = picked |
| | | }, |
| | | changeMultiColumns(index, picked) { |
| | | this.demos.multiColumns.columnPickedIndex = index |
| | | this.demos.multiColumns.columnPicked = picked |
| | | }, |
| | | changeCustomMultiColumns(index, picked) { |
| | | this.demos.customMultiColumns.columnPickedIndex = index |
| | | this.demos.customMultiColumns.columnPicked = picked |
| | | }, |
| | | addPickerItem(index, pickerList) { |
| | | if (pickerList.length > 0) { |
| | | pickerList = [{title: '全部', id: 0}].concat(pickerList) |
| | | } |
| | | |
| | | return pickerList |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | height: 100vh; |
| | | padding: 20rpx; |
| | | |
| | | .button { |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .picked-result { |
| | | width: 80%; |
| | | margin-top: 20rpx; |
| | | padding: 20rpx; |
| | | background-color: #f3f3f3; |
| | | color: #555; |
| | | font-size: 24rpx; |
| | | line-height: 1; |
| | | } |
| | | } |
| | | |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <view> |
| | | <view @click="showPicker"> |
| | | <slot></slot> |
| | | </view> |
| | | <view ref="picker" class="picker-pop" v-if="show" @touchmove="stopEvent"> |
| | | <view class="picker-mask" @click="cancel" :style="{height: screenHeight}"></view> |
| | | <view class="picker-panel" :style="pickerPanelTranslate"> |
| | | <view class="picker-action"> |
| | | <text class="cancel" @click="cancel" :style="pickerStyle.cancel">取消</text> |
| | | <text class="confirm" @click="confirm" :style="pickerStyle.confirm">确定</text> |
| | | </view> |
| | | <view class="picker-content"> |
| | | <view class="picker-column" v-for="(column, columnIndex) in columns" :key="columnIndex" |
| | | :style="pickerStyle.column[columnIndex]" :data-column="columnIndex" |
| | | @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"> |
| | | <view class="scroll-wrapper"> |
| | | <view class="scroll-list" :style="column.style"> |
| | | <view class="picker-item" v-for="(data, itemIndex) in column.pickerList" :key="itemIndex"> |
| | | <text class="picker-item-text">{{data[pickerKey.label]}}</text> |
| | | </view> |
| | | </view> |
| | | <view class="top-cover"></view> |
| | | <view class="top-cover-border"></view> |
| | | <view class="bottom-cover"></view> |
| | | <view class="bottom-cover-border"></view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | pickerList: { |
| | | value: Array, |
| | | require: true, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | pickerKey: { |
| | | value: Object, |
| | | default() { |
| | | return { |
| | | value: 'value', |
| | | label: 'label', |
| | | children: 'children' |
| | | } |
| | | } |
| | | }, |
| | | pickerStyle: { |
| | | value: Object, |
| | | default() { |
| | | return { |
| | | cancel: {}, |
| | | confirm: {}, |
| | | column: [] |
| | | } |
| | | } |
| | | }, |
| | | defaultValue: { |
| | | value: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | columnNum: { |
| | | value: Number, |
| | | default: 0 |
| | | }, |
| | | itemRotateDeg: { |
| | | value: Number, |
| | | default: 15 |
| | | }, |
| | | beforeSetColumn: { |
| | | value: Function, |
| | | default: null |
| | | }, |
| | | speedUpRatio: { |
| | | value: Number, |
| | | default: 1 |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | show: false, |
| | | reactModel: true, |
| | | columns: [], |
| | | systemInfo: uni.getSystemInfoSync(), |
| | | startScrollTop: 0, |
| | | startPickedIndex: 0, |
| | | scrollingColumnIndex: 0, |
| | | } |
| | | }, |
| | | watch: { |
| | | pickerList() { |
| | | this.init() |
| | | }, |
| | | defaultValue() { |
| | | this.init() |
| | | }, |
| | | }, |
| | | computed: { |
| | | pickerItemStyle() { |
| | | return function(pickedIndex, itemIndex) { |
| | | let distance = Math.abs(pickedIndex - itemIndex) |
| | | if (distance <= 3) { |
| | | return { |
| | | transform: 'rotateX(' + distance * this.itemRotateDeg + 'deg)' |
| | | } |
| | | } else { |
| | | return {} |
| | | } |
| | | } |
| | | }, |
| | | screenHeight() { |
| | | return this.systemInfo.screenHeight |
| | | }, |
| | | pickerItemHeight() { |
| | | return Math.floor(68 * this.systemInfo.windowWidth / 750) |
| | | }, |
| | | pickerPanelTranslate() { |
| | | if (this.show) { |
| | | return { |
| | | transform: "translate(0, -" + this.systemInfo.windowBottom + ");" |
| | | } |
| | | } else { |
| | | return { |
| | | transform: "translate(0, 100%);" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | }, |
| | | methods: { |
| | | stopEvent(event) { |
| | | event.stopPropagation() |
| | | }, |
| | | init() { |
| | | if (Array.isArray(this.pickerList[0])) { |
| | | this.pickerList.forEach((pickerList, index) => { |
| | | this.setColumn(index, pickerList) |
| | | }) |
| | | this.reactModel = false; |
| | | } else { |
| | | this.setColumn(0, this.pickerList) |
| | | } |
| | | }, |
| | | showPicker(event) { |
| | | this.stopEvent(event) |
| | | this.init() |
| | | if (this.inited) { |
| | | this.show = true |
| | | } else { |
| | | // #ifdef H5 |
| | | let $picker = this.$refs.picker |
| | | document.body.appendChild($picker) |
| | | // #endif |
| | | setTimeout(() => { |
| | | this.show = true |
| | | }, 20) |
| | | this.inited = true |
| | | } |
| | | this.$emit('click') // 传递click事件 |
| | | }, |
| | | confirm() { |
| | | let picked = {index: [], value: [], label: [], indexes: [],values: [], labels: []} |
| | | for (let column of this.columns) { |
| | | let columnPicked = this.columnPickedInfo(column) |
| | | if (columnPicked) { |
| | | picked.index = columnPicked.index |
| | | picked.value = columnPicked.value |
| | | picked.label = columnPicked.label |
| | | |
| | | picked.indexes.push(columnPicked.index) |
| | | picked.values.push(columnPicked.value) |
| | | picked.labels.push(columnPicked.label) |
| | | } else { |
| | | picked.indexes.push(null) |
| | | picked.values.push(null) |
| | | picked.labels.push(null) |
| | | } |
| | | } |
| | | this.$emit('confirm', picked) |
| | | this.hide() |
| | | }, |
| | | cancel() { |
| | | this.$emit('cancel') |
| | | this.hide() |
| | | }, |
| | | hide() { |
| | | this.show = false |
| | | }, |
| | | columnPickedInfo(column) { |
| | | if (column.pickerList.length < 1) { |
| | | return null |
| | | } |
| | | return { |
| | | index: column.pickedIndex, |
| | | value: column.pickerList[column.pickedIndex][this.pickerKey.value], |
| | | label: column.pickerList[column.pickedIndex][this.pickerKey.label], |
| | | } |
| | | }, |
| | | touchstart(e) { |
| | | this.scrollingColumnIndex = e.target.dataset.column |
| | | this.startScrollTop = e.changedTouches[0].pageY |
| | | this.startPickedIndex = this.columns[this.scrollingColumnIndex].pickedIndex |
| | | |
| | | this.columns[this.scrollingColumnIndex].scrollEventQueue = [{ |
| | | index: this.startPickedIndex, |
| | | time: +new Date() |
| | | }] |
| | | }, |
| | | touchmove(e) { |
| | | let scrollDistance = this.startScrollTop - e.changedTouches[0].pageY |
| | | let scrollIndex = Math.round(scrollDistance/this.pickerItemHeight) |
| | | let column = this.columns[this.scrollingColumnIndex] |
| | | let currentPickedIndex = column.pickedIndex |
| | | this.setColumnIndex(column, this.startPickedIndex + scrollIndex) |
| | | if (column.pickedIndex !== currentPickedIndex) { |
| | | this.scrollColumn(column, true) |
| | | } |
| | | }, |
| | | touchend(e) { |
| | | let column = this.columns[this.scrollingColumnIndex] |
| | | this.scrollColumn(column, false, true) |
| | | }, |
| | | setColumn(columnIndex, pickerList) { |
| | | if (columnIndex === 5 || (this.columnNum > 0 && columnIndex >= this.columnNum)) { |
| | | // limit max 5 columns |
| | | return |
| | | } |
| | | let columnPickerList = pickerList || [] |
| | | if (this.beforeSetColumn) { |
| | | // 在开始渲染列之前使用钩子动态修改pickerList,注意避免对pickerList修改以保证渲染不污染源数据 |
| | | columnPickerList = this.beforeSetColumn(columnIndex, columnPickerList) |
| | | } |
| | | if (columnPickerList.length < 1) { |
| | | if (this.columnNum === 0) { |
| | | // 动态列数,当前列为空,清除后面全部列 |
| | | this.columns = this.columns.filter(column => { |
| | | return column.index < columnIndex |
| | | }) |
| | | return |
| | | } else if (columnIndex < this.columnNum) { |
| | | // 固定列数,清除下一列,递归清除后面全部列 |
| | | this.setColumn(columnIndex + 1, []) |
| | | } else { |
| | | return |
| | | } |
| | | } |
| | | |
| | | let currentColumn = this.columns[columnIndex] || {} |
| | | let column = { |
| | | index: columnIndex, |
| | | scrollEventQueue: [], |
| | | pickerList: columnPickerList, |
| | | pickedIndex: 0, |
| | | style: { |
| | | "transition-property": "transform", |
| | | "transition-duration": "200", |
| | | "transform": "translateY(0)" |
| | | } |
| | | } |
| | | this.setColumnIndex(column, currentColumn.pickedIndex || 0) // 使得column的index维持在当前选择位置 |
| | | let defaultValue = this.defaultValue && this.defaultValue[columnIndex] !== false ? this.defaultValue[columnIndex] : false |
| | | if (currentColumn.pickedIndex === undefined && defaultValue !== false) { |
| | | column.pickerList.map((pickerItem, index) => { |
| | | if (pickerItem[this.pickerKey.value] == defaultValue) { |
| | | column.pickedIndex = index |
| | | } |
| | | }) |
| | | } |
| | | |
| | | this.scrollColumn(column) |
| | | this.$set(this.columns, columnIndex, column) |
| | | }, |
| | | setColumnIndex(column, index) { |
| | | index = index < 0 ? 0 : index |
| | | column.pickedIndex = Math.min(index, column.pickerList.length - 1) |
| | | }, |
| | | scrollColumn(column, needThrottle = false, needSpeedUp = false) { |
| | | let now = +new Date() |
| | | let lastScrollEvent = column.scrollEventQueue[column.scrollEventQueue.length-1] |
| | | if (needThrottle && lastScrollEvent.time && now < (lastScrollEvent.time + 100)) { |
| | | return |
| | | } |
| | | let speedUpIndex = 0 |
| | | if (needSpeedUp && this.speedUpRatio) { |
| | | // 模拟惯性效果,在touch事件接触后,根据最后两次滚动事件的速度生成滑动的距离。在touch过程中,保持触摸距离和滚动距离的一致 |
| | | if (column.scrollEventQueue.length > 1) { |
| | | lastScrollEvent = column.scrollEventQueue[column.scrollEventQueue.length-2] |
| | | } |
| | | let speed = (column.pickedIndex - lastScrollEvent.index) / (now - lastScrollEvent.time) |
| | | speedUpIndex = Math.floor(Math.pow(speed, 2) * 800 * this.speedUpRatio) // 使用二次方曲线放大加速效果,其中效果800为默认调试参数 |
| | | speedUpIndex = speed > 0 ? speedUpIndex : -speedUpIndex; |
| | | this.setColumnIndex(column, column.pickedIndex + speedUpIndex) |
| | | } |
| | | |
| | | column.scrollEventQueue.push({ |
| | | index: column.pickedIndex, |
| | | time: now |
| | | }) |
| | | |
| | | let translateY = column.pickedIndex * this.pickerItemHeight |
| | | column.style = { |
| | | "transition-property": "transform", |
| | | "transition-duration": "200", |
| | | "transform": "translateY(" + -translateY + ")" |
| | | } |
| | | |
| | | if (this.reactModel && column.pickerList[column.pickedIndex]) { |
| | | this.setColumn(column.index + 1, column.pickerList[column.pickedIndex][this.pickerKey.children]) |
| | | } |
| | | |
| | | this.$emit('change', column.index, this.columnPickedInfo(column)) |
| | | } |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .picker-mask { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | z-index: 999; |
| | | width: 750rpx; |
| | | background-color: rgba(0, 0, 0, .6); |
| | | } |
| | | |
| | | .picker-panel { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | width: 750rpx; |
| | | background-color: #fff; |
| | | transform: translate(0, 100%); |
| | | transition: transform .3s; |
| | | flex-direction: column; |
| | | } |
| | | .picker-action { |
| | | width: 750rpx; |
| | | height: 96rpx; |
| | | position: relative; |
| | | justify-content: space-between; |
| | | } |
| | | .confirm, .cancel { |
| | | padding: 30rpx; |
| | | font-size: 36rpx; |
| | | } |
| | | .confirm { |
| | | color: #007aff; |
| | | } |
| | | |
| | | .picker-content { |
| | | width: 750rpx; |
| | | height: 476rpx; |
| | | overflow: hidden; |
| | | position: relative; |
| | | } |
| | | .picker-column { |
| | | flex: 1; |
| | | font-size: 32rpx; |
| | | overflow: hidden; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .scroll-wrapper { |
| | | position: relative; |
| | | height: 476rpx; |
| | | flex-direction: column; |
| | | } |
| | | .top-cover, .bottom-cover { |
| | | width: 750rpx; |
| | | height: 204rpx; |
| | | position: absolute; |
| | | |
| | | transform: translateZ(0); |
| | | background-image: linear-gradient(to top,rgba(245, 245, 245, .2),rgba(245, 245, 245, .9)); |
| | | } |
| | | .top-cover { |
| | | top: 0; |
| | | } |
| | | .bottom-cover { |
| | | bottom: 0; |
| | | background-image: linear-gradient(to bottom,rgba(245, 245, 245,.2),rgba(245, 245, 245, .9)); |
| | | } |
| | | .top-cover-border, .bottom-cover-border { |
| | | position: absolute; |
| | | width: 750rpx; |
| | | height: 1px; |
| | | border-color: #ccc; |
| | | border-style: solid; |
| | | } |
| | | .top-cover-border { |
| | | top: 204rpx; |
| | | border-bottom-width: .5px; |
| | | } |
| | | .bottom-cover-border { |
| | | bottom: 204rpx; |
| | | border-top-width: .5px; |
| | | } |
| | | .scroll-list { |
| | | padding: 204rpx 0; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | } |
| | | .picker-item { |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 68rpx; |
| | | } |
| | | .picker-item-text { |
| | | flex: 1; |
| | | lines: 1; |
| | | text-overflow: ellipsis; |
| | | /*无法给text设定宽度,此处无效 */ |
| | | padding: 10rpx; |
| | | text-align: center; |
| | | font-size: 32rpx; |
| | | color: #333; |
| | | |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div> |
| | | <div @click.prevent.stop="showPicker"> |
| | | <slot></slot> |
| | | </div> |
| | | <div ref="picker" class="picker-pop" v-show="show" @touchmove.prevent.stop> |
| | | <div class="picker-mask" @click="cancel"></div> |
| | | <div class="picker-panel" :class="{'picker-panel-translate': show}"> |
| | | <div class="picker-action"> |
| | | <p class="cancel" @click="cancel" :style="pickerStyle.cancel">取消</p> |
| | | <p class="confirm" @click="confirm" :style="pickerStyle.confirm">确定</p> |
| | | </div> |
| | | <div class="picker-content"> |
| | | <div class="picker-column" v-for="(column, columnIndex) in columns" :key="columnIndex" |
| | | :style="pickerStyle.column[columnIndex]" :data-column="columnIndex" |
| | | @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"> |
| | | <div class="scroll-wrapper"> |
| | | <div class="top-cover"></div> |
| | | <div class="bottom-cover"></div> |
| | | <view class="scroll-list" :animation="column.animationData"> |
| | | <div v-for="(data, itemIndex) in column.pickerList" :key="itemIndex" > |
| | | <div class="picker-item" |
| | | <!-- #ifdef H5--> |
| | | :style="pickerItemStyle(column.pickedIndex, itemIndex)" |
| | | <!-- #endif--> |
| | | > |
| | | {{data[pickerKey.label]}} |
| | | </div> |
| | | </div> |
| | | </view> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | pickerList: { |
| | | value: Array, |
| | | require: true, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | pickerKey: { |
| | | value: Object, |
| | | default() { |
| | | return { |
| | | value: 'value', |
| | | label: 'label', |
| | | children: 'children' |
| | | } |
| | | } |
| | | }, |
| | | pickerStyle: { |
| | | value: Object, |
| | | default() { |
| | | return { |
| | | cancel: {}, |
| | | confirm: {}, |
| | | column: [] |
| | | } |
| | | } |
| | | }, |
| | | defaultValue: { |
| | | value: Array, |
| | | default() { |
| | | return [] |
| | | } |
| | | }, |
| | | columnNum: { |
| | | value: Number, |
| | | default: 0 |
| | | }, |
| | | itemRotateDeg: { |
| | | value: Number, |
| | | default: 15 |
| | | }, |
| | | beforeSetColumn: { |
| | | value: Function, |
| | | default: null |
| | | }, |
| | | speedUpRatio: { |
| | | value: Number, |
| | | default: 1 |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | show: false, |
| | | reactModel: true, |
| | | columns: [], |
| | | pickerItemHeight: Math.floor(68 * uni.getSystemInfoSync().windowWidth / 750), |
| | | startScrollTop: 0, |
| | | startPickedIndex: 0, |
| | | scrollingColumnIndex: 0, |
| | | } |
| | | }, |
| | | watch: { |
| | | pickerList() { |
| | | this.init() |
| | | }, |
| | | defaultValue() { |
| | | this.init() |
| | | }, |
| | | }, |
| | | computed: { |
| | | pickerItemStyle() { |
| | | return function(pickedIndex, itemIndex) { |
| | | let distance = Math.abs(pickedIndex - itemIndex) |
| | | if (distance <= 3) { |
| | | return { |
| | | transform: 'rotateX(' + distance * this.itemRotateDeg + 'deg)' |
| | | } |
| | | } else { |
| | | return {} |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | }, |
| | | methods: { |
| | | init() { |
| | | if (Array.isArray(this.pickerList[0])) { |
| | | this.pickerList.forEach((pickerList, index) => { |
| | | this.setColumn(index, pickerList) |
| | | }) |
| | | this.reactModel = false; |
| | | } else { |
| | | this.setColumn(0, this.pickerList) |
| | | } |
| | | |
| | | }, |
| | | showPicker() { |
| | | this.init() |
| | | if (this.inited) { |
| | | this.show = true |
| | | } else { |
| | | // #ifdef H5 |
| | | let $picker = this.$refs.picker |
| | | document.getElementsByTagName('uni-page')[0].appendChild($picker) |
| | | // #endif |
| | | setTimeout(() => { |
| | | this.show = true |
| | | }, 20) |
| | | this.inited = true |
| | | } |
| | | this.$emit('click') // 传递click事件 |
| | | }, |
| | | confirm() { |
| | | let picked = {index: [], value: [], label: [], indexes: [],values: [], labels: []} |
| | | for (let column of this.columns) { |
| | | let columnPicked = this.columnPickedInfo(column) |
| | | if (columnPicked) { |
| | | picked.index = columnPicked.index |
| | | picked.value = columnPicked.value |
| | | picked.label = columnPicked.label |
| | | |
| | | picked.indexes.push(columnPicked.index) |
| | | picked.values.push(columnPicked.value) |
| | | picked.labels.push(columnPicked.label) |
| | | } else { |
| | | picked.indexes.push(null) |
| | | picked.values.push(null) |
| | | picked.labels.push(null) |
| | | } |
| | | } |
| | | this.$emit('confirm', picked) |
| | | this.hide() |
| | | }, |
| | | cancel() { |
| | | this.$emit('cancel') |
| | | this.hide() |
| | | }, |
| | | hide() { |
| | | this.show = false |
| | | }, |
| | | columnPickedInfo(column) { |
| | | if (column.pickerList.length < 1) { |
| | | return null |
| | | } |
| | | return { |
| | | index: column.pickedIndex, |
| | | value: column.pickerList[column.pickedIndex][this.pickerKey.value], |
| | | label: column.pickerList[column.pickedIndex][this.pickerKey.label], |
| | | } |
| | | }, |
| | | touchstart(e) { |
| | | this.scrollingColumnIndex = e.currentTarget.dataset.column |
| | | this.startScrollTop = e.changedTouches[0].clientY |
| | | this.startPickedIndex = this.columns[this.scrollingColumnIndex].pickedIndex |
| | | |
| | | this.columns[this.scrollingColumnIndex].scrollEventQueue = [{ |
| | | index: this.startPickedIndex, |
| | | time: +new Date() |
| | | }] |
| | | }, |
| | | touchmove(e) { |
| | | let scrollDistance = this.startScrollTop - e.changedTouches[0].clientY |
| | | let scrollIndex = Math.round(scrollDistance/this.pickerItemHeight) |
| | | let column = this.columns[this.scrollingColumnIndex] |
| | | let currentPickedIndex = column.pickedIndex |
| | | this.setColumnIndex(column, this.startPickedIndex + scrollIndex) |
| | | if (column.pickedIndex !== currentPickedIndex) { |
| | | this.scrollColumn(column, true) |
| | | } |
| | | }, |
| | | touchend(e) { |
| | | let column = this.columns[this.scrollingColumnIndex] |
| | | this.scrollColumn(column, false, true) |
| | | }, |
| | | setColumn(columnIndex, pickerList) { |
| | | if (columnIndex === 5 || (this.columnNum > 0 && columnIndex >= this.columnNum)) { |
| | | // limit max 5 columns |
| | | return |
| | | } |
| | | let columnPickerList = pickerList || [] |
| | | if (this.beforeSetColumn) { |
| | | // 在开始渲染列之前使用钩子动态修改pickerList,注意避免对pickerList修改以保证渲染不污染源数据 |
| | | columnPickerList = this.beforeSetColumn(columnIndex, columnPickerList) |
| | | } |
| | | if (columnPickerList.length < 1) { |
| | | if (this.columnNum === 0) { |
| | | // 动态列数,当前列为空,清除后面全部列 |
| | | this.columns = this.columns.filter(column => { |
| | | return column.index < columnIndex |
| | | }) |
| | | return |
| | | } else if (columnIndex < this.columnNum) { |
| | | // 固定列数,清除下一列,递归清除后面全部列 |
| | | this.setColumn(columnIndex + 1, []) |
| | | } else { |
| | | return |
| | | } |
| | | } |
| | | |
| | | let currentColumn = this.columns[columnIndex] || {} |
| | | let column = { |
| | | index: columnIndex, |
| | | scrollEventQueue: [], |
| | | pickerList: columnPickerList, |
| | | pickedIndex: 0, |
| | | } |
| | | this.setColumnIndex(column, currentColumn.pickedIndex || 0) // 使得column的index维持在当前选择位置 |
| | | let defaultValue = this.defaultValue && this.defaultValue[columnIndex] !== false ? this.defaultValue[columnIndex] : false |
| | | if (currentColumn.pickedIndex === undefined && defaultValue !== false) { |
| | | column.pickerList.map((pickerItem, index) => { |
| | | if (pickerItem[this.pickerKey.value] == defaultValue) { |
| | | column.pickedIndex = index |
| | | } |
| | | }) |
| | | } |
| | | |
| | | this.scrollColumn(column) |
| | | this.$set(this.columns, columnIndex, column) |
| | | }, |
| | | setColumnIndex(column, index) { |
| | | index = index < 0 ? 0 : index |
| | | column.pickedIndex = Math.min(index, column.pickerList.length - 1) |
| | | }, |
| | | scrollColumn(column, needThrottle = false, needSpeedUp = false) { |
| | | let now = +new Date() |
| | | let lastScrollEvent = column.scrollEventQueue[column.scrollEventQueue.length-1] |
| | | if (needThrottle && lastScrollEvent.time && now < (lastScrollEvent.time + 100)) { |
| | | return |
| | | } |
| | | let speedUpIndex = 0 |
| | | if (needSpeedUp && this.speedUpRatio) { |
| | | // 模拟惯性效果,在touch事件接触后,根据最后两次滚动事件的速度生成滑动的距离。在touch过程中,保持触摸距离和滚动距离的一致 |
| | | if (column.scrollEventQueue.length > 1) { |
| | | lastScrollEvent = column.scrollEventQueue[column.scrollEventQueue.length-2] |
| | | } |
| | | let speed = (column.pickedIndex - lastScrollEvent.index) / (now - lastScrollEvent.time) |
| | | speedUpIndex = Math.floor(Math.pow(speed, 2) * 800 * this.speedUpRatio) // 使用二次方曲线放大加速效果,其中效果800为默认调试参数 |
| | | speedUpIndex = speed > 0 ? speedUpIndex : -speedUpIndex; |
| | | this.setColumnIndex(column, column.pickedIndex + speedUpIndex) |
| | | } |
| | | |
| | | column.scrollEventQueue.push({ |
| | | index: column.pickedIndex, |
| | | time: now |
| | | }) |
| | | |
| | | let translateY = column.pickedIndex * this.pickerItemHeight |
| | | column.animationData = uni.createAnimation({ |
| | | duration: 200, |
| | | timingFunction: 'linear', |
| | | }).translateY(-translateY).step().export() |
| | | |
| | | if (this.reactModel && column.pickerList[column.pickedIndex]) { |
| | | this.setColumn(column.index + 1, column.pickerList[column.pickedIndex][this.pickerKey.children]) |
| | | } |
| | | |
| | | this.$emit('change', column.index, this.columnPickedInfo(column)) |
| | | } |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .picker-pop { |
| | | .picker-mask { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | z-index: 999; |
| | | width: 100vw; |
| | | height: 100vh; |
| | | background-color: rgba(0, 0, 0, .6); |
| | | } |
| | | |
| | | .picker-panel { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | z-index: 999; |
| | | width: 100%; |
| | | background-color: #fff; |
| | | transform: translate(0, 100%); |
| | | transition: transform .3s; |
| | | |
| | | .picker-action { |
| | | display: flex; |
| | | position: relative; |
| | | justify-content: space-between; |
| | | |
| | | &:after { |
| | | content: ''; |
| | | position: absolute; |
| | | right: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | height: 1px; |
| | | transform: scaleY(.5); |
| | | background-color: #dedede; |
| | | } |
| | | |
| | | p { |
| | | color: #999; |
| | | padding: 30rpx; |
| | | line-height: 1; |
| | | font-size: 36rpx; |
| | | } |
| | | .confirm { |
| | | color: #007aff; |
| | | } |
| | | } |
| | | |
| | | .picker-content { |
| | | height: calc(68rpx * 7); |
| | | overflow: hidden; |
| | | position: relative; |
| | | display: flex; |
| | | |
| | | .picker-column { |
| | | flex: 1; |
| | | font-size: 32rpx; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .scroll-wrapper { |
| | | position: relative; |
| | | height: calc(68rpx * 7); |
| | | |
| | | .top-cover, .bottom-cover { |
| | | width: 100%; |
| | | position: absolute; |
| | | z-index: 1; |
| | | transform: translateZ(0); |
| | | height: calc(68rpx * 3); |
| | | background: linear-gradient(0deg,hsla(0,0%,100%,.3),hsla(0,0%,100%,.9)); |
| | | |
| | | &:before { |
| | | content: ''; |
| | | position: absolute; |
| | | right: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | height: 1px; |
| | | transform: scaleY(.5); |
| | | background-color: #dedede; |
| | | } |
| | | } |
| | | .top-cover { |
| | | top: 0; |
| | | } |
| | | .bottom-cover { |
| | | bottom: 0; |
| | | background: linear-gradient(180deg,hsla(0,0%,100%,.3),hsla(0,0%,100%,.9)); |
| | | |
| | | &:before { |
| | | top: 0; |
| | | } |
| | | } |
| | | .scroll-list { |
| | | padding-top: calc(68rpx * 3); |
| | | |
| | | .picker-item { |
| | | text-align: center; |
| | | font-size: 32rpx; |
| | | line-height: 68rpx; |
| | | height: 68rpx; |
| | | color: #333; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | .picker-panel-translate { |
| | | transform: translate(0, 0); |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | 由于官方picker是基于index维护默认选中,在复杂场景显得过于繁琐,另外官方picker在老版本安卓浏览器中无法显示(已提issue修复方案,后面应该会解决),所以就自己重新写了一套picker。 |
| | | 目前还不支持日期时间选择,仅用于替代下拉多列联动的数据选择。 |
| | | ## 属性/事件列表: |
| | | |
| | | | 属性/事件 | 必填 | 默认 | 功能 | |
| | | | :-----: | :-----: | :-----: | :----- | |
| | | | pickerList | 是 | [] | picker数据,支持多维,使用`children`存储多维数据 | |
| | | | pickerKey | 否 | {value: 'value',lable:'label',children: 'children'} | 用于指定用户自定义数据字段名和默认字段名对应关系 | |
| | | | pickerStyle | 否 | {} | 目前可以自定义按钮样式,列样式,参数格式见: `pickerStyle` | |
| | | | defaultValue | 否 | [] | 默认值,数组格式,和`pickerList`维数保持一致 | |
| | | | columnNum | 否 | 0 | 指定列,不传或者为0表示根据数据动态显示列数,最多限制5列 | |
| | | | itemRotateDeg | 否 | 15 | 每个选项滚动角度,模拟滚轴效果, 注意:该效果目前只支持H5 | |
| | | | beforeSetColumn | 否 | null | 每次更新列之前调用方法,参数:`columnIndex`,`pickerList`,其中`pickerList`对应当前列数据, 可使用该方法对列数据动态的处理,也可以用于ajax动态获取列数据。注意:如果未设置`columnNum`,只有`beforeSetColumn`返回空值或者超出5列才会停止渲染新的列 | |
| | | | speedUpRatio | 否 | 1 | 增加了滑动惯性特性,该参数可以设置惯性的速率比例。默认1为预设速率,设置为0则没有惯性。 | |
| | | | @confirm | 否 | null | 点击确定后触发,参数:`picked` | |
| | | | @change | 否 | null | 列选项更新的时候触发,参数:`columnIndex`, `columnPicked` | |
| | | | @cancel | 否 | null | 点击取消或者蒙版触发 | |
| | | |
| | | |
| | | ### pickerList: |
| | | ``` |
| | | // 联动多列 |
| | | [ |
| | | { |
| | | label: '选项1', |
| | | value: 1, |
| | | children: [ |
| | | { |
| | | label: '选项11', |
| | | value: 11, |
| | | children: [ |
| | | {label: '选项111', value: 111}, |
| | | ] |
| | | }, |
| | | ] |
| | | }, |
| | | ] |
| | | |
| | | // 非联动多列 |
| | | [ |
| | | [ |
| | | {label: '选项1', value: 1}, |
| | | {label: '选项2', value: 2}, |
| | | {label: '选项3', value: 3}, |
| | | ], |
| | | [ |
| | | {label: '选项1', value: 1}, |
| | | {label: '选项2', value: 2}, |
| | | {label: '选项3', value: 3}, |
| | | ], |
| | | ] |
| | | |
| | | ``` |
| | | |
| | | ### pickerStyle: |
| | | ``` |
| | | { |
| | | cancel: { |
| | | color: '#999', |
| | | }, |
| | | confirm: { |
| | | color: '#1CABEB', |
| | | }, |
| | | column: [ |
| | | {flex: 1}, |
| | | {flex: 1}, |
| | | {flex: 3}, |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | ### picked: |
| | | ``` |
| | | { |
| | | index: 1 |
| | | indexes: [3, 2, 1] |
| | | label: "1953年2分" |
| | | labels: ["3版", "2分", "1953年2分"] |
| | | value: 116 |
| | | values: [4, 115, 116] |
| | | } |
| | | ``` |
| | | |
| | | ### columnPicked: |
| | | ``` |
| | | { |
| | | index: 1 |
| | | label: "1953年2分" |
| | | value: 116 |
| | | } |
| | | ``` |
| | | |
| | | |
| | | ## Demo: |
| | | 引入picker不要uni-app自带picker冲突,例:MyPicker. |
| | | |
| | | #### 单列: |
| | | ``` |
| | | <my-picker :picker-list="" @confirm="confirm"> |
| | | </my-picker> |
| | | ``` |
| | | |
| | | #### 固定多列: |
| | | ``` |
| | | <my-picker |
| | | column-num="3" |
| | | :picker-list="" |
| | | @change="change" |
| | | @confirm="confirm"> |
| | | </my-picker> |
| | | ``` |
| | | |
| | | #### 完整参数演示: |
| | | ``` |
| | | <my-picker |
| | | column-num="3" |
| | | :picker-list="" |
| | | :picker-style="" |
| | | :picker-key="{value: 'id', label: 'title', children: 'sub'}" |
| | | :before-set-column="addPickerItem" |
| | | :default-value="[2,21,212]" |
| | | :item-rotate-deg="20" |
| | | @change="change" |
| | | @confirm="confirm"> |
| | | </my-picker> |
| | | ``` |
| | | |
| | | #### 非固定列: |
| | | ``` |
| | | <my-picker |
| | | :picker-list="" |
| | | @confirm="confirm"> |
| | | </my-picker> |
| | | ``` |
| | | |
| | | #### 完整Demo |
| | | ``` |
| | | <template> |
| | | <view class="container"> |
| | | <my-picker :picker-list="singleColumnPickerList" @confirm="confirm('singleColumn', $event)"> |
| | | <button class="button" type="primary">单列</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.singleColumn.picked"> |
| | | <h4>单列picker选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.singleColumn.picked, null, 4)"></pre> |
| | | </view> |
| | | |
| | | <my-picker |
| | | :picker-list="multiColumnsPickerList" |
| | | column-num="3" |
| | | @change="change('multiColumns', ...arguments)" |
| | | @confirm="confirm('multiColumns', $event)"> |
| | | <button class="button" type="primary">3列联动</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.multiColumns.picked"> |
| | | <h4>3列联动选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.multiColumns.picked, null, 4)"></pre> |
| | | </view> |
| | | <view class="picked-result" v-else-if="demos.multiColumns.columnPicked"> |
| | | <h4>多列联动第{{demos.multiColumns.columnPickedIndex + 1}}列更新:</h4> |
| | | <pre v-html="JSON.stringify(demos.multiColumns.columnPicked, null, 4)"></pre> |
| | | </view> |
| | | |
| | | <my-picker |
| | | column-num="3" |
| | | :picker-list="multiColumnsWithCustomKeyPickerList" |
| | | :picker-style="pickerStyle" |
| | | :picker-key="{value: 'id', label: 'title', children: 'sub'}" |
| | | :before-set-column="addPickerItem" |
| | | :default-value="[2,21,212]" |
| | | :item-rotate-deg="20" |
| | | @change="change('customMultiColumns', ...arguments)" |
| | | @confirm="confirm('customMultiColumns', $event)"> |
| | | <button class="button" type="primary">完整自定义参数联动</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.customMultiColumns.picked"> |
| | | <h4>完整自定义参数联动选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.customMultiColumns.picked, null, 4)"></pre> |
| | | </view> |
| | | <view class="picked-result" v-else-if="demos.customMultiColumns.columnPicked"> |
| | | <h4>完整自定义参数联动第{{demos.customMultiColumns.columnPickedIndex + 1}}列更新:</h4> |
| | | <pre v-html="JSON.stringify(demos.customMultiColumns.columnPicked, null, 4)"></pre> |
| | | </view> |
| | | |
| | | <my-picker |
| | | :picker-list="multiColumnsPickerList" |
| | | @confirm="confirm('dynamicColumns', $event)"> |
| | | <button class="button" type="primary">非固定列联动</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.dynamicColumns.picked"> |
| | | <h4>非固定列联动选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.dynamicColumns.picked, null, 4)"></pre> |
| | | </view> |
| | | |
| | | <my-picker |
| | | :picker-list="independentMultiColumnsPickerList" |
| | | @confirm="confirm('independentMultiColumns', $event)"> |
| | | <button class="button" type="primary">多列非联动</button> |
| | | </my-picker> |
| | | <view class="picked-result" v-if="demos.independentMultiColumns.picked"> |
| | | <h4>多列非联动选择结果:</h4> |
| | | <pre v-html="JSON.stringify(demos.independentMultiColumns.picked, null, 4)"></pre> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import MyPicker from '../../components/Picker'; |
| | | |
| | | export default { |
| | | components: {MyPicker}, |
| | | data() { |
| | | return { |
| | | demos: { |
| | | singleColumn: { |
| | | picked: null, |
| | | }, |
| | | multiColumns: { |
| | | picked: null, |
| | | columnPicked: null, |
| | | columnPickedIndex: null, |
| | | }, |
| | | customMultiColumns: { |
| | | picked: null, |
| | | columnPicked: null, |
| | | columnPickedIndex: null, |
| | | }, |
| | | dynamicColumns: { |
| | | picked: null, |
| | | columnPicked: null, |
| | | columnPickedIndex: null, |
| | | }, |
| | | independentMultiColumns: { |
| | | picked: null, |
| | | columnPicked: null, |
| | | }, |
| | | }, |
| | | pickerStyle: { |
| | | cancel: { |
| | | color: '#999', |
| | | 'font-size': '32rpx' |
| | | }, |
| | | confirm: { |
| | | color: 'green', |
| | | 'font-size': '32rpx' |
| | | }, |
| | | column: [ |
| | | {flex: 1}, |
| | | {flex: 1}, |
| | | {flex: 2}, |
| | | ] |
| | | }, |
| | | singleColumnPickerList: [ |
| | | {label: '选项1', value: 1}, |
| | | {label: '选项2', value: 2}, |
| | | {label: '选项3', value: 3}, |
| | | {label: '选项4', value: 4}, |
| | | {label: '选项5', value: 5}, |
| | | {label: '选项6', value: 6}, |
| | | {label: '选项7', value: 7}, |
| | | {label: '选项8', value: 8}, |
| | | {label: '选项9', value: 9}, |
| | | ], |
| | | multiColumnsPickerList: [ |
| | | { |
| | | label: '选项1', |
| | | value: 1, |
| | | children: [ |
| | | { |
| | | label: '选项11', |
| | | value: 11, |
| | | children: [ |
| | | {label: '选项111', value: 111}, |
| | | {label: '选项112', value: 112}, |
| | | {label: '选项113', value: 113}, |
| | | {label: '选项114', value: 114}, |
| | | {label: '选项115', value: 115}, |
| | | ] |
| | | }, |
| | | { |
| | | label: '选项12', |
| | | value: 12, |
| | | children: [ |
| | | {label: '选项121', value: 121}, |
| | | {label: '选项122', value: 122}, |
| | | {label: '选项123', value: 123}, |
| | | {label: '选项124', value: 124}, |
| | | {label: '选项125', value: 125}, |
| | | ] |
| | | }, |
| | | {label: '选项13', value: 13}, |
| | | {label: '选项14', value: 14}, |
| | | {label: '选项15', value: 15}, |
| | | ] |
| | | }, |
| | | { |
| | | label: '选项2', |
| | | value: 2, |
| | | children: [ |
| | | { |
| | | label: '选项21', |
| | | value: 21, |
| | | children: [ |
| | | {label: '选项211', value: 211}, |
| | | {label: '选项212', value: 212}, |
| | | {label: '选项213', value: 213}, |
| | | {label: '选项214', value: 214}, |
| | | {label: '选项215', value: 215}, |
| | | ] |
| | | }, |
| | | { |
| | | label: '选项22', |
| | | value: 22, |
| | | children: [ |
| | | {label: '选项221', value: 221}, |
| | | {label: '选项222', value: 222}, |
| | | {label: '选项223', value: 223}, |
| | | {label: '选项224', value: 224}, |
| | | {label: '选项225', value: 225}, |
| | | ] |
| | | }, |
| | | {label: '选项23', value: 23}, |
| | | {label: '选项24', value: 24}, |
| | | {label: '选项25', value: 25}, |
| | | ] |
| | | }, |
| | | {label: '选项3', value: 3}, |
| | | {label: '选项4', value: 4}, |
| | | {label: '选项5', value: 5}, |
| | | {label: '选项6', value: 6}, |
| | | {label: '选项7', value: 7}, |
| | | {label: '选项8', value: 8}, |
| | | {label: '选项9', value: 9}, |
| | | ], |
| | | multiColumnsWithCustomKeyPickerList: [ |
| | | { |
| | | title: '选项1', |
| | | id: 1, |
| | | sub: [ |
| | | { |
| | | title: '选项11', |
| | | id: 11, |
| | | sub: [ |
| | | {title: '选项111', id: 111}, |
| | | {title: '选项112', id: 112}, |
| | | {title: '选项113', id: 113}, |
| | | {title: '选项114', id: 114}, |
| | | {title: '选项115', id: 115}, |
| | | ] |
| | | }, |
| | | { |
| | | title: '选项12', |
| | | id: 12, |
| | | sub: [ |
| | | {title: '选项121', id: 121}, |
| | | {title: '选项122', id: 122}, |
| | | {title: '选项123', id: 123}, |
| | | {title: '选项124', id: 124}, |
| | | {title: '选项125', id: 125}, |
| | | ] |
| | | }, |
| | | {title: '选项13', id: 13}, |
| | | {title: '选项14', id: 14}, |
| | | {title: '选项15', id: 15}, |
| | | ] |
| | | }, |
| | | { |
| | | title: '选项2', |
| | | id: 2, |
| | | sub: [ |
| | | { |
| | | title: '选项21', |
| | | id: 21, |
| | | sub: [ |
| | | {title: '选项211', id: 211}, |
| | | {title: '选项212', id: 212}, |
| | | {title: '选项213', id: 213}, |
| | | {title: '选项214', id: 214}, |
| | | {title: '选项215', id: 215}, |
| | | ] |
| | | }, |
| | | { |
| | | title: '选项22', |
| | | id: 22, |
| | | sub: [ |
| | | {title: '选项221', id: 221}, |
| | | {title: '选项222', id: 222}, |
| | | {title: '选项223', id: 223}, |
| | | {title: '选项224', id: 224}, |
| | | {title: '选项225', id: 225}, |
| | | ] |
| | | }, |
| | | {title: '选项23', id: 23}, |
| | | {title: '选项24', id: 24}, |
| | | {title: '选项25', id: 25}, |
| | | ] |
| | | }, |
| | | {title: '选项3', id: 3}, |
| | | {title: '选项4', id: 4}, |
| | | {title: '选项5', id: 5}, |
| | | {title: '选项6', id: 6}, |
| | | {title: '选项7', id: 7}, |
| | | {title: '选项8', id: 8}, |
| | | {title: '选项9', id: 9}, |
| | | ], |
| | | independentMultiColumnsPickerList: [ |
| | | [ |
| | | {label: '选项1', value: 1}, |
| | | {label: '选项2', value: 2}, |
| | | {label: '选项3', value: 3}, |
| | | {label: '选项4', value: 4}, |
| | | {label: '选项5', value: 5}, |
| | | {label: '选项6', value: 6}, |
| | | {label: '选项7', value: 7}, |
| | | {label: '选项8', value: 8}, |
| | | {label: '选项9', value: 9}, |
| | | ], |
| | | [ |
| | | {label: '选项1', value: 1}, |
| | | {label: '选项2', value: 2}, |
| | | {label: '选项3', value: 3}, |
| | | {label: '选项4', value: 4}, |
| | | {label: '选项5', value: 5}, |
| | | {label: '选项6', value: 6}, |
| | | {label: '选项7', value: 7}, |
| | | {label: '选项8', value: 8}, |
| | | {label: '选项9', value: 9}, |
| | | ], |
| | | ] |
| | | } |
| | | }, |
| | | methods: { |
| | | confirm(type, picked) { |
| | | this.demos[type].picked = picked |
| | | }, |
| | | change(type, index, picked) { |
| | | this.demos[type].columnPickedIndex = index |
| | | this.demos[type].columnPicked = picked |
| | | }, |
| | | addPickerItem(index, pickerList) { |
| | | if (index === 2 && pickerList.length > 0) { |
| | | pickerList = [{title: '全部', id: 0}].concat(pickerList) |
| | | } |
| | | |
| | | return pickerList |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | height: 100vh; |
| | | padding: 20rpx; |
| | | |
| | | .button { |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .picked-result { |
| | | width: 80%; |
| | | margin-top: 20rpx; |
| | | padding: 20rpx; |
| | | background-color: #f3f3f3; |
| | | color: #555; |
| | | font-size: 24rpx; |
| | | line-height: 1; |
| | | } |
| | | } |
| | | |
| | | </style> |
| | | |
| | | ``` |
| | | |
| | | |
| | |
| | | <view class="container-page" style="padding: 0rpx;"> |
| | | <view> |
| | | <view class="form-item"> |
| | | <view class="label required">商品分类todo</view> |
| | | <view class="label required">商品分类</view> |
| | | <view class="m-l-a m-r-0 flex " :class="[!dto.category?'desc-gray':'']" @click="()=>{ |
| | | show_select_category=true |
| | | // show_select_category=true |
| | | $refs.picker_category.showPicker() |
| | | }"> |
| | | <view>{{dto.categoryStr||dto.category || '请选择'}}</view> |
| | | <u-icon class="m-l-a" name="arrow-right"></u-icon> |
| | |
| | | |
| | | } |
| | | }"> |
| | | <view>{{ '去设置'}}</view> |
| | | <view>{{ paramstr || '去设置'}}</view> |
| | | <u-icon class="m-l-a" name="arrow-right"></u-icon> |
| | | </view> |
| | | |
| | |
| | | </view> |
| | | </uni-popup> |
| | | |
| | | <dying318picker :pickerList="columns_categorys" ref="picker_category" :pickerKey="pickerKey"></dying318picker> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import environments from '@/environments' |
| | | import dying318picker from '@/components/dying318-picker/Picker.vue' |
| | | |
| | | import { |
| | | mapState |
| | |
| | | columns_categorys: [], |
| | | columns_levels: [], |
| | | // columns_params: [], //弹窗选择具体的值 |
| | | pickerKey: { |
| | | value: 'id', |
| | | lable: 'name', |
| | | children: 'children' |
| | | }, |
| | | cancel: { |
| | | color: '#999', |
| | | }, |
| | | confirm: { |
| | | color: '#20613D', |
| | | }, |
| | | // column: [ |
| | | // {flex: 1}, |
| | | // {flex: 1}, |
| | | // {flex: 3}, |
| | | // ] |
| | | } |
| | | }, |
| | | async onLoad(options) { |
| | | //tree |
| | | this.$http.request('get', '/api/flower/category/tree', {}).then(res => { |
| | | var data = res.data |
| | | this.columns_categorys = data || [] |
| | | console.log('columns_categorys',this.columns_categorys) |
| | | // this.columns_categorys = [data || []] |
| | | // this.columns_categorys[0].unshift({ |
| | | // label: '全部', |
| | | // value: '', |
| | | // children: [] |
| | | // }) |
| | | |
| | | }) |
| | | |
| | | this.$http.request('get', '/api/code/value', { |
| | | params: { |
| | | typeCode: 'FLOWER_LEVEL' |
| | | } |
| | | }).then(res => { |
| | | var data = res.data |
| | | this.columns_levels = [data || []] |
| | | this.columns_levels[0].unshift({ |
| | | label: '全部', |
| | | value: '' |
| | | }) |
| | | |
| | | }) |
| | | if (options.id) { |
| | | this.id = options.id |
| | | uni.setNavigationBarTitle({ |
| | |
| | | }) |
| | | } |
| | | |
| | | //tree |
| | | this.$http.request('get', '/api/flower/category/tree', {}).then(res => { |
| | | var data = res.data |
| | | this.columns_categorys = [data || []] |
| | | this.columns_categorys[0].unshift({ |
| | | label: '全部', |
| | | value: '', |
| | | children: [] |
| | | }) |
| | | |
| | | }) |
| | | |
| | | this.$http.request('get', '/api/code/value', { |
| | | params: { |
| | | typeCode: 'FLOWER_LEVEL' |
| | | } |
| | | }).then(res => { |
| | | var data = res.data |
| | | this.columns_levels = [data || []] |
| | | this.columns_levels[0].unshift({ |
| | | label: '全部', |
| | | value: '' |
| | | }) |
| | | |
| | | }) |
| | | } |
| | | |
| | | }, |
| | |
| | | |
| | | }, |
| | | computed: { |
| | | ...mapState(['currentInfo']) |
| | | ...mapState(['currentInfo']), |
| | | paramstr() { |
| | | if (this.dto && this.dto.params) { |
| | | var strs = [] |
| | | for (var i of this.dto.params) { |
| | | if (i.value) { |
| | | strs.push(i.value) |
| | | } |
| | | } |
| | | return strs.join(',') |
| | | } |
| | | return '' |
| | | } |
| | | }, |
| | | components: { |
| | | |
| | | dying318picker |
| | | } |
| | | } |
| | | </script> |
| | |
| | | <template> |
| | | <view class="order-records"> |
| | | <view class="tj-container-p"> |
| | | <view class="tj-container"> |
| | | <view class="tj-each"> |
| | | <view class="tj-container flex"> |
| | | <view class="tj-each flex1"> |
| | | <view class="value">9</view> |
| | | <view class="label">买家</view> |
| | | </view> |
| | | <view class="tj-each"> |
| | | <view class="tj-each flex1"> |
| | | <view class="value">9扎</view> |
| | | <view class="label">交易</view> |
| | | </view> |
| | | <view class="tj-each"> |
| | | <view class="tj-each flex1"> |
| | | <view class="value">0.00</view> |
| | | <view class="label">理赔</view> |
| | | </view> |
| | | <view class="tj-each"> |
| | | <view class="tj-each flex1"> |
| | | <view class="value">401.12</view> |
| | | <view class="label">交易合计</view> |
| | | </view> |
| | |
| | | padding: 30rpx; |
| | | |
| | | .tj-container { |
| | | height: 148rpx; |
| | | // height: 148rpx; |
| | | background: #FFFFFF; |
| | | border-radius: 8rpx; |
| | | |
| | | padding-top: 16rpx; |
| | | padding-bottom: 16rpx; |
| | | .tj-each { |
| | | text-align: center; |
| | | .label { |
| | | margin-top: 16rpx; |
| | | font-weight: 400; |
| | | font-size: 24rpx; |
| | | color: #000000; |