|
@@ -1,4 +1,5 @@
|
|
|
<script>
|
|
|
+import { refer } from "./api/index";
|
|
|
export default {
|
|
|
name: "PopoverSelect",
|
|
|
props: {
|
|
@@ -15,16 +16,16 @@ export default {
|
|
|
// 参照弹窗标题
|
|
|
title: {
|
|
|
type: String,
|
|
|
- default: "TITLE",
|
|
|
+ dafault: () => {
|
|
|
+ return "TITEL";
|
|
|
+ },
|
|
|
},
|
|
|
// 作为 value 唯一标识的键名,绑定值
|
|
|
valueKey: {
|
|
|
type: String,
|
|
|
- default: "name",
|
|
|
- },
|
|
|
- // 作为 value 唯一标识的键名,显示值
|
|
|
- showKey: {
|
|
|
- type: String,
|
|
|
+ dafault: () => {
|
|
|
+ return "code";
|
|
|
+ },
|
|
|
},
|
|
|
// 默认查询参数
|
|
|
queryParams: {
|
|
@@ -34,135 +35,273 @@ export default {
|
|
|
// 组件大小
|
|
|
size: {
|
|
|
type: String,
|
|
|
- default: "mini",
|
|
|
+ dafault: () => {
|
|
|
+ return "mini";
|
|
|
+ },
|
|
|
},
|
|
|
// 提示
|
|
|
placeholder: {
|
|
|
type: String,
|
|
|
- default: "",
|
|
|
+ dafault: () => {
|
|
|
+ return "";
|
|
|
+ },
|
|
|
},
|
|
|
// 是否可读
|
|
|
readonly: {
|
|
|
type: Boolean,
|
|
|
- default: false,
|
|
|
+ dafault: () => {
|
|
|
+ return false;
|
|
|
+ },
|
|
|
},
|
|
|
// 是否禁止
|
|
|
disabled: {
|
|
|
type: Boolean,
|
|
|
- default: false,
|
|
|
+ dafault: () => {
|
|
|
+ return false;
|
|
|
+ },
|
|
|
},
|
|
|
// 是否清除
|
|
|
clearable: {
|
|
|
type: Boolean,
|
|
|
- default: false,
|
|
|
+ dafault: () => {
|
|
|
+ return false;
|
|
|
+ },
|
|
|
},
|
|
|
// 是否多选
|
|
|
multiple: {
|
|
|
type: Boolean,
|
|
|
- default: false,
|
|
|
+ dafault: () => {
|
|
|
+ return false;
|
|
|
+ },
|
|
|
},
|
|
|
// 需映射源数据
|
|
|
source: Object,
|
|
|
// 参照内外映射
|
|
|
dataMapping: Object,
|
|
|
},
|
|
|
- emits: ["hide"],
|
|
|
- components: {
|
|
|
- TableDialog: () => import("./components/index.vue"),
|
|
|
- },
|
|
|
+ components: {},
|
|
|
data() {
|
|
|
return {
|
|
|
- // popover宽度
|
|
|
- width: "",
|
|
|
- // 选中data
|
|
|
+ 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: {
|
|
|
- showValue() {
|
|
|
- const { showKey, valueKey } = this.$props;
|
|
|
- return this.data.length === 1 ? this.data[0][showKey || valueKey] : "";
|
|
|
+ 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, oldProp) {
|
|
|
- if (!newProp) {
|
|
|
- this.data = [];
|
|
|
- }
|
|
|
+ handler: function (newProp) {
|
|
|
+ if (!newProp) this.selectData = [];
|
|
|
},
|
|
|
immediate: true,
|
|
|
},
|
|
|
},
|
|
|
methods: {
|
|
|
- // 打开弹窗
|
|
|
- handleAsyncOpenDialog() {
|
|
|
- this.$nextTick(() => {
|
|
|
- const { setVisible } = this.$refs.TableDialog;
|
|
|
- setVisible(true);
|
|
|
- });
|
|
|
- },
|
|
|
- // 新增操作
|
|
|
- handleAdd(prop) {
|
|
|
- this.data = prop;
|
|
|
- this.handleUpdate(this.data);
|
|
|
- },
|
|
|
- // 删除操作
|
|
|
- handleDelete(prop) {
|
|
|
- this.data.splice(prop, 1);
|
|
|
- this.handleUpdate(this.data);
|
|
|
- },
|
|
|
- // 更新操作
|
|
|
- handleUpdate(prop) {
|
|
|
- const { source, multiple, valueKey, dataMapping } = this.$props;
|
|
|
- // 多选
|
|
|
- if (multiple) {
|
|
|
- const updateData = prop.map((item) => item[valueKey]);
|
|
|
- this.$emit("input", updateData);
|
|
|
+ // show dialog
|
|
|
+ async show() {
|
|
|
+ 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;
|
|
|
+ this.$notify.success({ title: msg });
|
|
|
+ } else {
|
|
|
+ this.$notify.warning({ title: msg });
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ //
|
|
|
+ } finally {
|
|
|
+ this.loading = false;
|
|
|
}
|
|
|
+ },
|
|
|
+ // reset list
|
|
|
+ async resetList() {
|
|
|
+ const { type, queryParams } = this.$props;
|
|
|
+ this.model = { type, ...this.model, ...queryParams };
|
|
|
+ const { page, model } = this;
|
|
|
+ await this.fetchList(model, page);
|
|
|
+ },
|
|
|
+ // query list
|
|
|
+ async queryList() {
|
|
|
+ const { page, model } = this;
|
|
|
+ await this.fetchList(model, page);
|
|
|
+ },
|
|
|
+ // row click
|
|
|
+ rowClick(prop) {
|
|
|
+ const { multiple } = this.$props;
|
|
|
// 单选
|
|
|
- if (!multiple) {
|
|
|
- const updateData = prop[0][valueKey];
|
|
|
- this.$emit("input", updateData);
|
|
|
- // 更新映射数据
|
|
|
- for (let key in dataMapping) {
|
|
|
- source[key] = prop[0][dataMapping[key]];
|
|
|
- console.log(source[key]);
|
|
|
- console.log(prop[0][dataMapping[key]]);
|
|
|
- }
|
|
|
- console.log("prop", prop, source, this.$props);
|
|
|
- this.$emit("update:source", source);
|
|
|
+ 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 } = 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);
|
|
|
},
|
|
|
},
|
|
|
- created() {
|
|
|
- this.$nextTick(() => {
|
|
|
- const { clientWidth } = this.$refs.PopoverSelect;
|
|
|
- this.width = clientWidth;
|
|
|
- });
|
|
|
- },
|
|
|
+ created() {},
|
|
|
mounted() {},
|
|
|
destroyed() {},
|
|
|
};
|
|
|
</script>
|
|
|
<template>
|
|
|
- <div ref="PopoverSelect" style="position: relative">
|
|
|
+ <div>
|
|
|
<el-input
|
|
|
- v-model="showValue"
|
|
|
+ v-model="innerValue"
|
|
|
:size="size"
|
|
|
:disabled="disabled"
|
|
|
+ :readonly="readonly"
|
|
|
:clearable="clearable"
|
|
|
:placeholder="placeholder"
|
|
|
- readonly
|
|
|
- style="width: 100%; cursor: pointer"
|
|
|
- @click.native.stop="handleAsyncOpenDialog"
|
|
|
>
|
|
|
- <template #suffix>
|
|
|
- <el-icon class="el-icon-more"></el-icon>
|
|
|
- </template>
|
|
|
+ <el-button
|
|
|
+ :disabled="disabled"
|
|
|
+ slot="append"
|
|
|
+ icon="el-icon-search"
|
|
|
+ @click="show()"
|
|
|
+ ></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
|
|
|
+ >
|
|
|
+ <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="visible = false"> 取 消 </el-button>
|
|
|
+ <el-button :size="size" @click="confirm(selectData)"> 确 定 </el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
<div
|
|
|
style="
|
|
|
position: absolute;
|
|
@@ -173,7 +312,7 @@ export default {
|
|
|
overflow: hidden;
|
|
|
"
|
|
|
>
|
|
|
- <div v-if="multiple && data.length > 1">
|
|
|
+ <div v-if="multiple && selectData.length">
|
|
|
<el-popover
|
|
|
:offset="-10"
|
|
|
:width="width"
|
|
@@ -184,10 +323,10 @@ export default {
|
|
|
placement="bottom-start"
|
|
|
>
|
|
|
<el-tag slot="reference" :size="size" style="margin-right: 10px">
|
|
|
- + {{ data.length }}
|
|
|
+ + {{ selectData.length }}
|
|
|
</el-tag>
|
|
|
<el-tag
|
|
|
- v-for="(item, index) in data"
|
|
|
+ v-for="(tag, index) in selectData"
|
|
|
:size="size"
|
|
|
hit
|
|
|
closable
|
|
@@ -195,24 +334,15 @@ export default {
|
|
|
display: 'flex',
|
|
|
justifyContent: 'space-between',
|
|
|
alignItems: 'center',
|
|
|
- margin: data.length - 1 === index ? '0' : '0 0 5px 0',
|
|
|
+ margin: selectData.length - 1 === index ? '0' : '0 0 5px 0',
|
|
|
}"
|
|
|
- @close="handleDelete(index)"
|
|
|
+ @close="deleteTag(index)"
|
|
|
>
|
|
|
- {{ item[showKey || valueKey] }}
|
|
|
+ {{ tag.name }}
|
|
|
</el-tag>
|
|
|
</el-popover>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <table-dialog
|
|
|
- v-model="data"
|
|
|
- ref="TableDialog"
|
|
|
- :type="type"
|
|
|
- :title="title"
|
|
|
- :multiple="multiple"
|
|
|
- :queryParams="queryParams"
|
|
|
- @confirm="handleAdd"
|
|
|
- ></table-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
<style scoped></style>
|