|
@@ -0,0 +1,311 @@
|
|
|
+<template>
|
|
|
+ <Layout ref="layoutRef" :type="type" :placeholder="placeholder" :trigger="trigger" :value="activeLabel"
|
|
|
+ @visible="onVisibleChange">
|
|
|
+ <div class="filter-list" slot="empty">
|
|
|
+ <div class="filter-item" :class="{ 'active': item.value === activeValue, 'highlight': item.disabled && isCustom }"
|
|
|
+ v-for="item in options" :key="item.label" :label="item.label" :value="item.value" @click="handleChange(item)">
|
|
|
+ <el-popover v-if="item.disabled" class="custom-popover" :append-to-body="false" placement="right-end"
|
|
|
+ :trigger="popoverTrigger" :offset="12" v-model="showPopover" ref="customPricePopover">
|
|
|
+ <div class="custom-money">
|
|
|
+ <div class="custom-money-item">
|
|
|
+ 从<el-input class="price-input" :class="{ 'focus': price.min }" v-model="price.min"
|
|
|
+ oninput="value=value.replace(/^\D*([0-9]\d*\.?\d{0,2})?.*$/,'$1')" maxlength="9"></el-input>万
|
|
|
+ </div>
|
|
|
+ <div class="custom-money-item">
|
|
|
+ 至<el-input class="price-input" :class="{ 'focus': price.max }" v-model="price.max"
|
|
|
+ oninput="value=value.replace(/^\D*([0-9]\d*\.?\d{0,2})?.*$/,'$1')" maxlength="9"></el-input>万
|
|
|
+ </div>
|
|
|
+ <div class="custom-money-button">
|
|
|
+ <el-button type="primary" @click.stop="onSubmitPrice">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div slot="reference" class="custom-label">
|
|
|
+ <span>{{ item.label }}</span>
|
|
|
+ <i class="el-icon-arrow-right"></i>
|
|
|
+ </div>
|
|
|
+ </el-popover>
|
|
|
+ <span v-else>{{ item.label }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Layout>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { Popover, Button, Input } from 'element-ui'
|
|
|
+import { amountRangeData } from '@/assets/js/selector.js'
|
|
|
+import Layout from '@/components/filter-items/Layout.vue'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'SelectContainer',
|
|
|
+ components: {
|
|
|
+ [Popover.name]: Popover,
|
|
|
+ [Button.name]: Button,
|
|
|
+ [Input.name]: Input,
|
|
|
+ Layout
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ type: {
|
|
|
+ type: String,
|
|
|
+ default: 'dropdown'
|
|
|
+ },
|
|
|
+ trigger: {
|
|
|
+ type: String,
|
|
|
+ default: 'hover'
|
|
|
+ },
|
|
|
+ placeholder: {
|
|
|
+ type: String,
|
|
|
+ default: '金额区间'
|
|
|
+ },
|
|
|
+ popoverTrigger: {
|
|
|
+ type: String,
|
|
|
+ default: 'hover'
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ type: [String, Object],
|
|
|
+ default: null
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ }
|
|
|
+ },
|
|
|
+ model: {
|
|
|
+ prop: 'value',
|
|
|
+ event: 'change'
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ activeValue: this.value,
|
|
|
+ isCustom: false, // 当前是否是自定义选项
|
|
|
+ price: {
|
|
|
+ min: '',
|
|
|
+ max: ''
|
|
|
+ },
|
|
|
+ showPopover: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ activeLabel() {
|
|
|
+ const price = this.activeValue
|
|
|
+ if (price) {
|
|
|
+ const priceArr = price.split('-')
|
|
|
+ if (priceArr.length > 1) {
|
|
|
+ const min = priceArr[0]
|
|
|
+ const max = priceArr[1]
|
|
|
+ if (min && max) {
|
|
|
+ if (min === '0') {
|
|
|
+ return `${max}万以下`
|
|
|
+ } else {
|
|
|
+ return `${min}-${max}万`
|
|
|
+ }
|
|
|
+ } else if (!min) {
|
|
|
+ return `${max}万以下`
|
|
|
+ } else if (!max) {
|
|
|
+ return `${min}万以上`
|
|
|
+ } else {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ value: {
|
|
|
+ immediate: true,
|
|
|
+ handler(val) {
|
|
|
+ this.setState(val)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ onVisibleChange(flag) {
|
|
|
+ this.isFocus = flag
|
|
|
+ if (flag) {
|
|
|
+ this.setState(this.activeValue)
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.showPopover) {
|
|
|
+ setTimeout(() => {
|
|
|
+ // popover在下拉框展示时需要重新计算位置,通过先将popover弹框透明度将为0等位置计算完成后再恢复
|
|
|
+ this.$refs.customPricePopover[0].updatePopper()
|
|
|
+ const $popover = this.$root.$el.querySelector('.custom-popover > .el-popover')
|
|
|
+ $popover.style.opacity = '1'
|
|
|
+ }, 300)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ compareMinMax() {
|
|
|
+ const { min, max } = this.price
|
|
|
+ const hasMinAndMax = String(min).length && String(max).length
|
|
|
+ if (hasMinAndMax && Number(min) > Number(max)) {
|
|
|
+ this.price.max = min
|
|
|
+ this.price.min = max
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onSubmitPrice() {
|
|
|
+ this.compareMinMax()
|
|
|
+ const { min, max } = this.price
|
|
|
+ if (!min && !max) return
|
|
|
+ this.activeValue = `${min}-${max}`
|
|
|
+ this.options.forEach(item => {
|
|
|
+ if (item.label === '自定义') {
|
|
|
+ item.value = `${min}-${max}`
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.isCustom = true
|
|
|
+ this.$refs.layoutRef.$refs.dropdownRef.hide()
|
|
|
+ this.$refs.customPricePopover[0].doClose()
|
|
|
+ this.$emit('change', this.activeValue)
|
|
|
+ },
|
|
|
+ handleChange(item) {
|
|
|
+ if (item.label !== '自定义') {
|
|
|
+ this.activeValue = item.value
|
|
|
+ this.isCustom = false
|
|
|
+ this.price.min = ''
|
|
|
+ this.price.max = ''
|
|
|
+ this.$refs.layoutRef.$refs.dropdownRef.hide()
|
|
|
+ this.$refs.customPricePopover[0].doClose()
|
|
|
+ this.$emit('change', this.activeValue)
|
|
|
+ } else {
|
|
|
+ this.isCustom = true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ getState() {
|
|
|
+ return {
|
|
|
+ label: this.activeLabel,
|
|
|
+ value: this.activeValue,
|
|
|
+ isCustom: this.isCustom
|
|
|
+ }
|
|
|
+ },
|
|
|
+ setState(data) {
|
|
|
+ this.isCustom = false
|
|
|
+ if (data) {
|
|
|
+ const valueArr = this.options.filter(v => !v.disabled).map(t => t.value)
|
|
|
+ if (valueArr.includes(data)) {
|
|
|
+ this.activeValue = data
|
|
|
+ } else {
|
|
|
+ const priceArr = data.split('-')
|
|
|
+ const min = priceArr[0]
|
|
|
+ const max = priceArr[1]
|
|
|
+ this.isCustom = true
|
|
|
+ this.price.min = min
|
|
|
+ this.price.max = max
|
|
|
+ this.activeValue = data
|
|
|
+ this.showPopover = true
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const $popover = this.$root.$el.querySelector('.custom-popover > .el-popover')
|
|
|
+ $popover.style.opacity = '0'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.activeValue = data
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.filter-list {
|
|
|
+ min-width: 140px;
|
|
|
+ padding: 8px 0;
|
|
|
+ border: 1px solid $color_main;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 5px;
|
|
|
+ margin-top: 2px;
|
|
|
+
|
|
|
+ .filter-item {
|
|
|
+ padding: 4px 16px;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 22px;
|
|
|
+ color: #1d1d1d;
|
|
|
+ text-align: left;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: #ECECEC;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ background: #ECECEC;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.highlight {
|
|
|
+ color: $color_main;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ display: inline-block;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .custom-label {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+
|
|
|
+ .el-icon-arrow-right {
|
|
|
+ margin-right: -8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .custom-popover {
|
|
|
+ .custom-money {
|
|
|
+ padding: 12px;
|
|
|
+ margin-left: 4px;
|
|
|
+ border: 1px solid $color_main;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ &-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-button {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+
|
|
|
+ .el-button {
|
|
|
+ width: 60px;
|
|
|
+ height: 28px;
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep {
|
|
|
+ .el-popover {
|
|
|
+ margin-left: 16px;
|
|
|
+ border-color: $color_main;
|
|
|
+ padding: 0;
|
|
|
+ border: 0;
|
|
|
+ background: transparent;
|
|
|
+ }
|
|
|
+
|
|
|
+ .price-input {
|
|
|
+ width: 88px;
|
|
|
+ height: 24px;
|
|
|
+ margin: 0 4px;
|
|
|
+
|
|
|
+ .el-input__inner {
|
|
|
+ height: 100%;
|
|
|
+ padding: 0 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.focus {
|
|
|
+ .el-input__inner {
|
|
|
+ border-color: $color_main;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|