基于Element-ui 表单弹窗列表选择封装

不知道怎么描述这个东西了。。el-select下拉框大家都知道,但是下拉框只能选择一个,而且如果数据太多的话也不太容易选择,所以这里就是封装了组件包含对应的弹窗,就是能实现多选,而且列表也是分页展示的,选择完之后将对应的名称展示在文本框中,传给后端对应的用逗号隔开(用什么隔开都可以,跟后端商量)的id

大致的效果图就是: 

 

这个关联合同就是我们封装的,输入框添加了disabled,不可编辑的,只能通过点击右侧弹窗来进行选择。点击弹窗之后的效果图: 

这里我们要考虑的就是:

  1. 点击弹窗要展示出列表,进行选择,选择完之后点击确定要将对应的名称展示出来,多个就用逗号隔开,然后拿到对应id对应赋值。
  2. 第二就是回显的问题,当我们选择完之后再次点击弹窗,这时候要将我们已选择数据在列表上进行回显勾选,后台返回数据的时候,我们要根据id依次查询对应的数据,将对应的名称展示出来,然后点击弹窗的时候同样的进行数据回显勾选 

这里直接附上代码: 

index.vue 

<template>
<div>
  <el-input placeholder="请选择" :size="size" :disabled="inpDisabled" style="line-hight:40px" v-model="name" class="input-with-select">
    <el-button slot="append" :disabled="btnDisabled" @click="showUserSelect" icon="el-icon-search"></el-button>
  </el-input>
  <!-- 合同列表 -->
  <ContractSelectDialog
    ref="contractSelect"
    @doSubmit="selectionsToInput"
    :selectData="selectData"
    :single="single"
  />
</div>
</template>
<script>
import ContractSelectDialog from './contractSelectDialog'
import ContractService from '@/api/contract/ContractService'
export default {
  data () {
    return {
      name: '',
      selectData: [],
      contractService: null
    }
  },
  props: {
    size: {
      type: String,
      default: 'small'
    },
    value: {
      type: String,
      default: ''
    },
    btnDisabled: {
      type: Boolean,
      default: false
    },
    inpDisabled: {
      type: Boolean,
      default: true
    },
    single: {  // 是否启用单选
      type: Boolean,
      default: false
    }
  },
  components: {
    ContractSelectDialog
  },
  created () {
    this.contractService = new ContractService()
  },
  watch: {
    value: {
      handler (newVal) {
        this.selectData = []
        if (newVal) {
          newVal.split(',').forEach((id) => { // 回显拿数据
            this.contractService.queryById(id).then(({data}) => {
              if (data && data.id !== '') {
                this.selectData.push(data)
              }
            })
          })
        }
      },
      immediate: true,
      deep: false
    },
    selectData: {
      handler (newVal) {
        this.name = newVal.map(contract => contract.contractName).join(',')
      },
      immediate: false,
      deep: false
    }
  },
  methods: {
    // 设置选中
    selectionsToInput (selections) {
      this.selectData = selections
      this.$emit('getInfo', this.selectData)
    },
    // 显示列表
    showUserSelect () {
      this.$refs.contractSelect.init()
    }
  }
}
</script>
<style>
.el-form-item__content .el-input-group {
  vertical-align: middle;
}
.el-tag + .el-tag {
  margin-left: 5px;
  margin-bottom: 5px;
}
</style>

对应的弹窗组件 

<template>
  <div>
    <el-dialog
      title="合同选择"
      width="1000px"
      :close-on-click-modal="false"
      :append-to-body="true"
      v-dialogDrag
      class="userDialog"
      :visible.sync="visible"
    >
      <el-container style="height: 500px">
        <el-container>
          <el-header style="text-align: left; font-size: 12px; height: 30px">
            <el-form
              size="small"
              :inline="true"
              ref="searchForm"
              :model="searchForm"
              @keyup.enter.native="refreshList()"
              @submit.native.prevent
            >
              <el-form-item prop="contractNo">
                <el-input
                  size="small"
                  v-model="searchForm.contractNo"
                  placeholder="合同编号"
                  clearable
                ></el-input>
              </el-form-item>
              <el-form-item prop="contracntName">
                <el-input
                  size="small"
                  v-model="searchForm.contracntName"
                  placeholder="合同名称"
                  clearable
                ></el-input>
              </el-form-item>
              <el-form-item>
                <el-button
                  type="primary"
                  @click="refreshList()"
                  size="small"
                  icon="el-icon-search"
                  >查询</el-button
                >
                <el-button
                  @click="resetSearch()"
                  size="small"
                  icon="el-icon-refresh-right"
                >重置</el-button>
              </el-form-item>
            </el-form>
          </el-header>
          <el-main>
            <el-table
              :data="dataList"
              v-loading="loading"
              size="small"
              border
              ref="contractTable"
              @select="handleSelectionChange"
              height="calc(100% - 40px)"
              style="width: 100%"
            >
              <el-table-column
                type="selection"
                header-align="center"
                align="center"
                width="50"
              >
              </el-table-column>
              <el-table-column
                prop="contractNo"
                header-align="center"
                align="left"
                sortable="custom"
                min-width="90"
                label="合同编号"
              >
              </el-table-column>
              <el-table-column
                prop="contractName"
                header-align="center"
                align="left"
                sortable="custom"
                min-width="90"
                label="合同名称"
              >
              </el-table-column>
              <el-table-column
                prop="contractAmount"
                header-align="center"
                align="left"
                sortable="custom"
                min-width="110"
                label="合同金额"
              >
              </el-table-column>
              <el-table-column
                prop="oppositeCompany"
                header-align="center"
                align="center"
                sortable="custom"
                min-width="110"
                label="对方单位"
              >
              </el-table-column>
              <el-table-column
                prop="signDate"
                header-align="center"
                align="left"
                sortable="custom"
                min-width="110"
                label="签订时间"
              >
            </el-table-column>
            </el-table>
            <el-pagination
              @size-change="sizeChangeHandle"
              @current-change="currentChangeHandle"
              :current-page="pageNo"
              :page-sizes="[5, 10, 50, 100]"
              :page-size="pageSize"
              :total="total"
              layout="total, sizes, prev, pager, next, jumper"
            >
            </el-pagination>
          </el-main>
        </el-container>
      </el-container>
      <span slot="footer" class="dialog-footer">
        <el-button
          size="small"
          @click="visible = false"
          icon="el-icon-circle-close"
          >关闭</el-button
        >
        <el-button
          size="small"
          type="primary"
          icon="el-icon-circle-check"
          @click="doSubmit()"
          >确定</el-button
        >
      </span>
    </el-dialog>
  </div>
</template>
<script>
export default {
  data() {
    return {
      searchForm: {
        contractNo: '',
        contracntName: ''
      },
      dataListAllSelections: [], // 所有选中的数据包含跨页数据
      idKey: "id", // 标识列表数据中每一行的唯一键的名称(需要按自己的数据改一下)
      dataList: [],
      pageNo: 1,
      pageSize: 10,
      total: 0,
      orders: [],
      loading: false,
      visible: false,
    };
  },
  props: {
    selectData: {
      type: Array,
      default: () => {
        return [];
      },
    },
    // 是否启用单选
    single: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    init() {
      this.visible = true;
      this.$nextTick(() => {
        this.dataListAllSelections = JSON.parse(JSON.stringify(this.selectData));
        this.resetSearch();
      });
    },
    // 获取数据列表
    refreshList() {
      this.loading = true;
      this.$http({
        url: "/contract/list", // 自己的接口路径
        method: "get",
        params: {
          current: this.pageNo,
          size: this.pageSize,
          orders: this.orders,
          ...this.searchForm,
        },
      }).then(({ data }) => {
        this.dataList = data.records;
        this.total = data.total;
        this.pageNo = data.current;
        this.loading = false;
        this.$nextTick(() => {
          this.setSelectRow();
        });
      });
    },
    // 每页数
    sizeChangeHandle(val) {
      this.pageSize = val;
      this.pageNo = 1;
      this.refreshList();
    },
    // 当前页
    currentChangeHandle(val) {
      this.pageNo = val;
      this.refreshList();
    },
    // 排序
    resetSearch() {
      this.$refs.searchForm.resetFields();
      this.refreshList();
    },
    // 选中数据
    handleSelectionChange(selection, row) {
      if (this.single && selection.length > 1) {
        this.$refs.contractTable.clearSelection();
        this.$refs.contractTable.toggleRowSelection(row);
      }
      this.dataListAllSelections = this.single ? [row] : selection
    },
    // 设置选中的方法
    setSelectRow() {
      this.$refs.contractTable.clearSelection();
      if (!this.dataListAllSelections || this.dataListAllSelections.length <= 0) {
        return;
      }
      for (let i = 0; i < this.dataList.length; i++) {
        if (this.dataListAllSelections.some(item => item[this.idKey] == this.dataList[i][this.idKey])) {
          // 设置选中,记住table组件需要使用ref="table"
          this.$refs.contractTable.toggleRowSelection(this.dataList[i], true);
        }
      }
    },
    doSubmit() {
      this.visible = false;
      this.$emit("doSubmit", this.dataListAllSelections);
    },
  },
};
</script>
<style lang="scss">
.userDialog {
  .el-dialog__body {
    padding: 10px 0px 0px 10px;
    color: #606266;
    font-size: 14px;
    word-break: break-all;
  }
  .el-main {
    padding: 20px 20px 5px 20px;
    .el-pagination {
      margin-top: 5px;
    }
  }
}
</style>

使用: 

组件默认是多选,可以传入single为true来启用单选

​
<template>
  <div>
    <el-form
      size="small"
      :model="inputForm"
      ref="inputForm"
      v-loading="loading"
      :disabled="formReadOnly"
      label-width="120px"
    >
      <el-row :gutter="15">
        <el-col :span="12">
          <el-form-item label="关联合同" prop="associatedContracts" :rules="[]">
            <ContractSelect
              :value="inputForm.associatedContracts"
              @getInfo="getContranct"
            />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>
<script>
import ContractSelect from '@/components/contractSelect/index.vue'
export default {
  data() {
    return {
      title: '',
      method: '',
      visible: false,
      loading: false,
      inputForm: {
        id: '',
        associatedContracts: '', // 关联合同
      },
    }
  },
  components: { ContractSelect },
  methods: {
    // 关联合同
    getContranct(selections) {
      this.inputForm.associatedContracts = selections.map(item => item.id).join(',')
    }
  }
}
</script>

猜你喜欢

转载自blog.csdn.net/m0_51431448/article/details/128535650