InputSelect.vue 2.1 KB
<template>
    <van-popup :show="show" position="bottom"
        :teleport="teleport"
        class="input-select">
        <van-picker
            title="请选择或录入"
            :columns="array"
            :columns-field-names="fieldNames"
            v-model="innerValue"
            @confirm="onConfirm"
            @cancel="onCancel"
        >
            <template #columns-top>
                <van-field v-model="customValue" placeholder="请输入" clearable maxlength="100"/>
            </template>
        </van-picker>
    </van-popup>
</template>

<script>
export default {
    props: {
        show: Boolean,
        value: [String, Number],
        fieldNames: {
            type: Object,
            default: () => {
                return {text: 'name', value: 'value'}
            }
        },
        // 字典
        dict: {
            type: Array,
            required: true
        },
        teleport: [String, Element]
    },
    emits: ['update:show', 'update:value', 'change'],
    data() {
        return {
            innerValue: undefined,
            customValue: ''
        }
    },
    computed: {
        array() {
            const array = this.dict || []
            const result = array.filter(e => e.value.startsWith(this.customValue))
            if (result.length) {
                return [...result]
            }
            return [{
                [this.fieldNames.text]: this.customValue,
                [this.fieldNames.value]: this.customValue
            }]
        }
    },
    methods: {
        onConfirm({ selectedValues, selectedOptions }) {
            this.$emit('update:value', selectedValues[0])
            this.$emit('change', selectedOptions[0] || {})
            this.$emit('update:show', false)
            this.customValue = ''
        },
        onCancel() {
            this.$emit('update:show', false)
        }
    },
    watch: {
        value: {
            handler(value) {
                if (value == null) return
                this.innerValue = [value]
            },
            immediate: true
        },
    }
}
</script>

<style lang="less" scoped>

</style>