<script> import { refer } from "./api/index"; export default { name: "PopoverSelect", props: { // 参照类型 ,对应后端 type: { type: String, require: true, }, // v-model value: { type: [Array, String], require: true, }, // 参照弹窗标题 title: { type: String, dafault: () => { return "TITEL"; }, }, // 作为 value 唯一标识的键名,绑定值 valueKey: { type: String, dafault: () => { return "code"; }, }, // 默认查询参数 queryParams: { type: Object, default: () => ({}), }, // 组件大小 size: { type: String, dafault: () => { return "mini"; }, }, // 提示 placeholder: { type: String, dafault: () => { return ""; }, }, // 是否可读 readonly: { type: Boolean, dafault: () => { return false; }, }, // 是否禁止 disabled: { type: Boolean, dafault: () => { return false; }, }, // 是否清除 clearable: { type: Boolean, dafault: () => { return false; }, }, // 是否多选 multiple: { type: Boolean, dafault: () => { return false; }, }, // 需映射源数据 source: Object, // 参照内外映射 dataMapping: Object, }, components: {}, data() { return { width: "50%", page: { pageNum: 1, pageSize: 25, total: 0 }, layout: "total, prev, pager, next, sizes, jumper", pageSizes: [25, 50, 100], visible: false, loading: false, model: { search: "", isPage: true, }, data: [], selectData: [], }; }, computed: { innerValue() { const { value, multiple } = this.$props; return multiple ? "" : value; }, TableColumnTemp() { const { type } = this.$props; const documents = require(`./components/${type}`).default; return documents.filter((document) => document.key); }, }, watch: { "$props.value": { handler: function (newProp) { if (!newProp) this.selectData = []; }, immediate: true, }, }, methods: { // open dialog async open() { this.visible = true; await this.resetList(); }, // hide dialog async hide() { this.visible = false; }, // fetch list async fetchList(prop, page) { try { this.loading = true; const { pageNum, pageSize } = page; const { code, msg, rows, total } = await refer(prop, { pageNum, pageSize, }); if (code === 200) { this.data = rows; this.page.total = total; } } catch (err) { // } finally { this.loading = false; } }, // reset list async resetList() { const { type, queryParams } = this.$props; this.model = { ...queryParams, ...this.model, search: "", type, }; await this.fetchList(this.model, this.page); }, // query list async queryList() { await this.fetchList(this.model, this.page); }, // row click rowClick(prop) { const { multiple } = this.$props; // 单选 if (!multiple) this.$refs.multipleTable.clearSelection(); [prop].forEach((row) => this.$refs.multipleTable.toggleRowSelection(row)); }, // row double click async rowDblclick(prop) { const { multiple } = this.$props; if (!multiple) await this.confirm([prop]); }, // selection change selectionChange(prop) { this.selectData = prop; }, // page size change async pageSizeChange(prop) { this.page.pageSize = prop; await this.queryList(); }, // page number change async pageNumberChange(prop) { this.page.pageNum = prop; await this.queryList(); }, // confirm async confirm(prop) { const { multiple } = this.$props; await this.hide(); await this.update(multiple ? prop : prop[0]); }, // delete tag deleteTag(prop) { this.selectData.splice(prop, 1); this.update(this.selectData); }, // update update(prop) { const { source, multiple, valueKey, dataMapping, type } = this.$props; // update v-model const vModel = multiple ? prop.map((item) => item[valueKey]) : prop[valueKey]; this.$emit("input", vModel); // update data mapping for (let key in dataMapping) { source[key] = prop[dataMapping[key]]; } this.$emit("update:source", source); // emit change this.$emit("change", prop, source, type); }, }, created() {}, mounted() {}, destroyed() {}, }; </script> <template> <div> <el-input v-model="innerValue" :size="size" :disabled="disabled" :readonly="readonly" :clearable="clearable" :placeholder="placeholder" > <el-button :disabled="disabled" slot="append" icon="el-icon-search" @click="open" ></el-button> </el-input> <el-dialog :title="`${title}(${multiple ? '多选' : '单选'})`" :width="width" :visible.sync="visible" :close-on-click-modal="false" :close-on-press-escape="false" append-to-body @close="hide" > <el-form v-loading="loading" :size="size" :inline="true" :model="model" @submit.native.prevent > <el-form-item prop="search"> <el-input v-model="model.search" @change="queryList" @keydown.enter="queryList" > </el-input> </el-form-item> <el-form-item> <el-button icon="el-icon-refresh" @click="resetList"></el-button> </el-form-item> <el-table ref="multipleTable" :data="data" :size="size" height="45vh" highlight-current-row style="width: 100%; margin-bottom: 20px" @row-click="rowClick" @row-dblclick="rowDblclick" @selection-change="selectionChange" > <el-table-column width="55" type="selection" align="center"> </el-table-column> <el-table-column v-for="(column, index) in TableColumnTemp" :key="index" :prop="column.key" :label="column.title" :width="column.width" show-overflow-tooltip > </el-table-column> </el-table> <el-pagination :layout="layout" :total="page.total" :page-sizes="pageSizes" :small="size === 'mini'" :page-size="page.pageSize" :current-page="page.pageNum" background @size-change="pageSizeChange" @current-change="pageNumberChange" > </el-pagination> </el-form> <div style="margin-top: 20px; text-align: right"> <el-button :size="size" @click="hide"> 取 消 </el-button> <el-button :size="size" @click="confirm(selectData)"> 确 定 </el-button> </div> </el-dialog> <div style=" position: absolute; left: 10px; top: 50%; transform: translateY(-50%); padding-right: 30px; overflow: hidden; " > <div v-if="multiple && selectData.length"> <el-popover :offset="-10" :width="width" :visible-arrow="false" title="" content="" trigger="click" placement="bottom-start" > <el-tag slot="reference" :size="size" style="margin-right: 10px"> + {{ selectData.length }} </el-tag> <el-tag v-for="(tag, index) in selectData" :size="size" hit closable :style="{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', margin: selectData.length - 1 === index ? '0' : '0 0 5px 0', }" @close="deleteTag(index)" > {{ tag.name }} </el-tag> </el-popover> </div> </div> </div> </template> <style scoped></style>