index.vue 9.71 KB
<style lang="scss">
    .qg-input-refer {
        position: relative;

        .el-select {
            width: 100%;
        }

        > .el-button {
            position: absolute;
            right: 2px;
            padding: 5px;
            top: 50%;
            transform: translateY(-50%);
        }

        .el-input {
            width: 100%;
        }
    }

    .qg-input-refer--dialog {
        .el-dialog__body {
            padding-top: 0;
            padding-bottom: 0;
        }

        .qg-search-form {
            border-bottom: 1px solid #eaeaea;
        }

        .opt-bar {
            padding-bottom: 0;
        }

        .qg-table {
            padding-left: 0;
            padding-right: 0;
        }
    }
</style>

<template>
    <div class="qg-input-refer">
        <el-select
            ref="qgInputRefer"
            v-model="selectValue"
            remote
            filterable
            reserve-keyword
            :multiple="multiple"
            placeholder="搜索"
            :remote-method="remoteMethod"
            :loading="loading"
            :disabled="disabled"
            @change="handleChange"
        >
            <el-option
                v-for="(item,key) in options"
                :key="key"
                :label="item[props.label]"
                :value="key"
            >
                <slot name="option" :item="item.data"/>
            </el-option>
        </el-select>
        <el-button icon="el-icon-tickets" type="text" @click="openTable"/>
    </div>
</template>
<script>
    export default {
        name: 'QgInputRefer',
        components: {},
        props: {
            value: {
                type: [String, Number, Array],
                default: ''
            },
            defaultText: {
                type: String,
                default: ''
            },
            defaultData: {
                type: [Object, Array],
                default: () => {
                }
            },
            request: {
                type: Function,
                default: () => {
                }
            },
            component: {
                type: Object,
                default: null
            },
            componentProps: {
                type: Object,
                default: null
            },
            suggestRequest: {
                type: Function,
                default: null
            },
            props: {
                type: Object,
                default: () => {
                    return {
                        label: 'name',
                        value: 'id'
                    };
                }
            },
            multiple: {
                type: Boolean,
                default: false
            },
            disabled: {
                type: Boolean,
                default: false
            },
            ucAjaxPrefix: {
                type: String,
                default: 'dev-uc'
            }
        },
        data() {
            return {
                options: [],
                list: [],
                loading: false,
                states: [],
                selectValue: null,
                selectedData: {},
                visible: false
            };
        },
        watch: {
            defaultData(newVal, oldVal) {
                if (newVal && !oldVal) {
                    this.initOption();
                }
            },
            value(newVal, oldVal) {
                if (newVal) {
                    // this.initOption();
                } else if (newVal === '' || newVal === null) {
                    this.selectValue = null;
                }
            }
        },
        created() {
        },
        mounted() {
            if (this.suggestRequest) {
                this.remoteMethod();
            }
        },
        methods: {
            handleChange() {
                if (this.multiple) {
                    const temp = {};
                    console.log(this.options, this.selectValue);
                    this.selectValue.forEach(item => {
                        const data = this.options[item].data;
                        if (data || this.selectedData[item]) {
                            temp[item] = data || this.selectedData[item];
                        }
                    });
                    this.selectedData = temp;
                } else {
                    this.selectedData = {};
                    this.selectedData[this.selectValue] = this.options[this.selectValue].data;
                }
                this.$emit('input', this.selectValue);
            },
            initOption() {
                if (!(this.value && (this.defaultText || this.defaultData))) {
                    return;
                }
                const options = this.options;
                let selectedData = null;
                if (!options[this.value] && this.value) {
                    if (Array.isArray(this.value) && Array.isArray(this.defaultData)) {
                        selectedData = {};
                        this.defaultData.forEach(item => {
                            options[item[this.props.value]] = {};
                            options[item[this.props.value]][this.props.label] = item[this.props.label] || '';
                            options[item[this.props.value]]['data'] = item;
                            selectedData[item[this.props.label]] = item;
                        });
                    } else {
                        options[this.value] = {};
                        options[this.value][this.props.label] = this.defaultText || '';
                        if (this.defaultData) {
                            options[this.value][this.props.label] = this.defaultData[this.props.label] || '';
                            options[this.value]['data'] = this.defaultData;
                        } else {
                            options[this.value]['data'] = {};
                            options[this.value]['data'][this.props.label] = this.defaultText;
                        }
                        const tmp = {};
                        tmp[this.value] = options[this.value].data;
                        selectedData = tmp;
                    }
                    this.options = options;
                }
                this.selectedData = selectedData;
                this.selectValue = this.value;
            },
            remoteMethod(query) {
                this.loading = true;
                this.suggestRequest(query).then(res => {
                    this.loading = false;
                    if (!res.data) {
                        this.options = {};
                        return;
                    }
                    if (Array.isArray(res.data)) {
                        this.options = this.convertData(res.data);
                    } else if (Array.isArray(res.data.list)) {
                        this.options = this.convertData(res.data.list);
                    }
                }).catch(() => {
                });
            },
            convertData(data) {
                const obj = {};
                data.forEach((e) => {
                    obj[e[this.props.value]] = {};
                    obj[e[this.props.value]][this.props.label] = e[this.props.label];
                    obj[e[this.props.value]]['data'] = e;
                });
                for (const selectedDataKey in this.selectedData) {
                    obj[selectedDataKey] = {};
                    obj[selectedDataKey][this.props.label] = this.selectedData[selectedDataKey][this.props.label] || '';
                    obj[selectedDataKey]['data'] = this.selectedData[selectedDataKey];
                }
                return obj;
            },
            handleCallback(action, data) {
                console.log(action, data);
                if (action === 'ok') {
                    if (!this.multiple && data && data.id) {
                        this.$emit('input', data.id);
                        const temp = {};
                        temp[data.id] = data;
                        this.selectValue = data.id;
                        this.selectedData = temp;
                        this.options[this.selectValue] = {};
                        this.options[this.selectValue][this.props.label] = data[this.props.label];
                        this.options[this.selectValue].data = data;
                    }
                    if (this.multiple && data && Array.isArray(data)) {
                        this.selectValue = [];
                        this.selectedData = {};
                        data.forEach(item => {
                            this.selectValue.push(item.id);
                            this.options[item.id] = {};
                            this.options[item.id][this.props.label] = item[this.props.label];
                            this.options[item.id].data = item;
                            this.selectedData[item.id] = item;
                        });
                        this.$emit('input', this.selectValue);
                    }
                }
            },
            openTable() {
                if (this.disabled) {
                    return;
                }
                const dialog = this.$qgDialog({
                    title: '选择',
                    width: '800px',
                    customClass: 'qg-input-refer--dialog',
                    component: this.component,
                    props: {
                        ...this.componentProps,
                        selected: this.selectedData,
                        multiple: this.multiple,
                        callback: (action, data) => {
                            this.handleCallback(action, data);
                            dialog.close();
                        }
                    }
                });
            }
        }
    };
</script>