自定义列表里面实现多选功能

需求

我们在开发过程中有时候会遇到列表里面会有多选,然后列表样式也要进行自定义。这里我们如果直接使用ElementUI组件el-table表格的时候这里实现起来可能比较复杂不方便,我们这里手写自定义一下列表里面多选的功能。

实现效果如下图所示:

在这里插入图片描述

具体实现代码如下

1- 我们这里先建一个子组件LiteratureTable.vue

<template>
  <div class="mainComponent">
    <div v-if="tableData.length" class="allCheck">
      <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" v-if="$_has('documentDatabase:download')" @change="handleCheckAllChange">全选</el-checkbox>
    </div>
    <div style="text-align: center;padding: 20px 0;" v-else>
      <el-tag type="warning">暂无数据</el-tag>
    </div>
    <div class="tableList">
      <el-checkbox-group v-model="checkedCities" @change="handleCheckedCitiesChange">
        <el-checkbox class="tableItem" v-for="item in tableData" :label="item.literatureId" :key="item.literatureId">
          <div class="itemPart">
            <div class="TopPart">
              <div class="TopLeft">
                <div class="title">
                  <span class="centerTitle">{{item.title || '无'}}</span>
                  <span class="centerNumber">{{item.code || '无'}}</span>
                </div>
              </div>
              <div class="topRight" v-if="!followupSelectvalue">
                <template v-if="$_has('documentDatabase:edit')">
                  <i class="iconFont el-icon-edit" @click.prevent="editHandel(item)">编辑</i>
                  <el-divider direction="vertical"></el-divider>
                </template>
                <!-- <i class="iconFont el-icon-download" @click.prevent="downloadHandel(item.literatureId)">下载</i> -->
                <!-- <i class="iconFont el-icon-download"></i>
                <DownloadFileForInspection
                  style="margin: 0 -10px;"
                  textColor="#67C23A"
                  btnName="下载"
                  type="text"
                  :url="'/literature/literature/downloadUrl'"
                  :data="{ literatureId: item.literatureId }"
                  method="post"
                /> -->
                <!-- <el-divider direction="vertical"></el-divider> -->
                <i v-if="$_has('documentDatabase:delete')" class="iconFont el-icon-delete" @click.prevent="deleItem(item.literatureId)">删除</i>
              </div>
              <div class="topRight" v-else>
                <el-button type="primary" @click="addselectLiteratureId(item)" size="mini">选中</el-button>
              </div>
            </div>
            <div class="BottomText">
              <div class="text-tag">
                <!-- <span>{{ Projectnamepocket(item.projectId, 'allProject') }}</span>
                |
                <span>{{ tagListPocket(item.derivation, 'Derivation') }}</span>
                |
                <span>{{ tagListPocket(item.type, 'Type') }}</span>
                |
                <span>{{ item.publishYear }}</span>
                |
                <span>{{ tagListPocket(item.lang, 'Lang') }}</span>
                |
                <span>{{ item.provenance || '无' }}</span>
                |
                <span>{{ item.downloadCount || '无' }}</span> -->
                {{ item.tagName || '无' }}
              </div>
              <div>
                {{ item.created_at }}
              </div>
            </div>
          </div>
        </el-checkbox>
      </el-checkbox-group>
    </div>

     <el-dialog title="编辑" :visible.sync="editVisible" width="460px">
      <el-form
        :inline="false"
        class="edit-form"
        ref="editForm"
        :model="editForm"
        label-width="145px">
        <el-form-item
          :rules="{ required: true, message: '请输入标题', trigger: 'blur' }"
          label="标题"
          prop="title">
          <el-input v-model="editForm.title" placeholder="请输入标题" clearable></el-input>
        </el-form-item>
        <el-form-item
          :rules="{ required: true, message: '请选择项目', trigger: 'change' }"
          label="项目"
          prop="projectId">
          <SelectGeneric
            @change="projectValueChange(editForm.projectId)"
            :select.sync="editForm.projectId"
            filterable
            multiple
            :options="'allProject' | pocketOptions"
            placeholder="请选择项目"
          >
          </SelectGeneric>
        </el-form-item>
        <el-form-item
          :rules="{ required: true, message: '请选择年限', trigger: 'change' }"
          label="发表年限"
          prop="publishYear">
          <el-date-picker
            v-model="editForm.publishYear"
            :picker-options="pickerOptions"
            type="year"
            format="yyyy"
            value-format="yyyy"
            placeholder="请选择年限">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="来源" prop="provenance">
          <el-input v-model="editForm.provenance" placeholder="请输入来源" clearable></el-input>
        </el-form-item>
        <el-form-item label="影响因子" prop="influence">
          <!-- <el-input type="number" v-model="editForm.influence" placeholder="请输入影响因子" clearable></el-input> -->
          <MyInputNumber style="width: 200px;" v-model="editForm.influence" :min="0" :max="1000" :precision="3" placeholder="请输入影响因子" clearable></MyInputNumber>
        </el-form-item>
        <el-form-item
          v-if="derivationOptions.length > 0"
          :rules="{ required: true, message: '请选择出处', trigger: 'change' }"
          label="出处"
          prop="derivationId">
          <SelectGeneric
            :select.sync="editForm.derivationId"
            :options="derivationOptions"
            placeholder="请选择出处"
            multiple
            collapse-tags
            clearable
          >
          </SelectGeneric>
        </el-form-item>

        <el-form-item
          v-for="(activeFormItem, i) in activeFormItems"
          :key="i"
          :label="activeFormItem.label"
          :prop="activeFormItem.shortName"
          :rules="{ required: !!activeFormItem.required, message: '请选择' + activeFormItem.label, trigger: 'change' }"
        >
          <el-cascader
            v-if="activeFormItem.type === 'cascader'"
            :options="activeFormItem.ch"
            v-model="editForm[activeFormItem.shortName]"
            :show-all-levels="false"
            :props="cascaderProps"
            :placeholder="'请选择' + activeFormItem.label"
            clearable
            filterable>
          </el-cascader>
          <SelectGeneric
            v-else
            collapse-tags
            filterable
            clearable
            :multiple="activeFormItem.type === 'multiple'"
            :select.sync="editForm[activeFormItem.shortName]"
            :options="activeFormItem.ch"
            :placeholder="'请选择' + activeFormItem.label"
          >
          </SelectGeneric>
        </el-form-item>

      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="editVisible = false">取 消</el-button>
        <el-button type="primary" @click="editConfirm">确 定</el-button>
      </div>
    </el-dialog>

    <el-dialog title="下载文献" :visible.sync="downloadVisible" width="460px" @closed="downloadClose">
      <el-form
        class="communication-form"
        ref="downloadForm"
        :model="downloadForm"
        label-width="80px">
        <el-form-item
          label="文献目的"
          prop="Goals"
          :rules="{ required: true, message: '请选文献目的', trigger: 'change' }">
          <el-radio-group v-model="downloadForm.Goals">
            <el-radio label="DoctorNeeds">医生需求</el-radio>
            <el-radio label="SelfLearning">自我学习</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item
          label="医生编号"
          prop="DoctorNo"
          v-if="downloadForm.Goals === 'DoctorNeeds'"
          :rules="{ required: true, message: '请输入医生编号', trigger: 'blur' }">
          <el-input v-model="downloadForm.DoctorNo" placeholder="请输入医生编号" clearable></el-input>
        </el-form-item>
        <el-form-item
          label="项目"
          prop="ProjectId"
          :rules="{ required: true, message: '请选择项目', trigger: 'change' }">
          <SelectGeneric
            :select.sync="downloadForm.ProjectId"
            :options="'allProject' | pocketOptions"
            placeholder="请选择项目"
            filterable
          >
          </SelectGeneric>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="downloadVisible = false">取 消</el-button>
        <el-button type="primary" @click="downloadConfirm">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { downloadByUrl } from '@utils/index'
export default {
  props: ['tableData', 'followupSelectvalue'],
  data () {
    return {
      downloadVisible: false,
      downloadForm: {
        Goals: 'DoctorNeeds',
        DoctorNo: undefined,
        ProjectId: undefined
      },
      selectLiteratureId: null,
      cascaderProps: {
        multiple: true,
        emitPath: false,
        checkStrictly: false,
        label: 'label',
        value: 'value',
        children: 'ch'
      },
      editVisible: false,
      editForm: {
        relationId: [],
        derivationId: []
      },
      derivationOptions: [],
      pickerOptions: {
        disabledDate: (val) => {
          var date = new Date()
          if (val.getFullYear() >= 2010 && val.getFullYear() <= date.getFullYear()) {
            return false
          } else {
            return true
          }
        }
      },
      checkAll: false,
      checkedCities: [],
      cities: [
        {
          literatureId: '1',
          name: '1'
        },
        {
          literatureId: '2',
          name: '2'
        },
        {
          literatureId: '3',
          name: '3'
        }
      ],
      isIndeterminate: false,
      activeFormItems: [],
      activeFormField: {}
    }
  },
  watch: {
  },
  methods: {
    projectValueChange (val) {
      if (val !== null && val !== '') {
        // this.editForm.derivationId = []
        this.$store.dispatch('scholarlyLiterature/getDerivationList', { ProjectId: val }).then(res => {
          this.derivationOptions = res.data
        })
      } else {
        this.editForm.derivationId = []
        this.derivationOptions = []
      }
    },
    // 获取项目名称
    Projectnamepocket (value, type, defalult) {
      var pocketLabel = []
      for (const i in this.$store.state.tool.pocket) {
        if (i === type) {
          if (Array.isArray(value)) {
            for (const item of value) {
              for (const v of this.$store.state.tool.pocket[type]) {
                if (item === v.value) {
                  pocketLabel.push(v.label)
                }
              }
            }
          } else {
            for (const v of this.$store.state.tool.pocket[type]) {
              if (value === v.value) {
                pocketLabel.push(v.label)
              }
            }
          }
          break
        }
      }
      return pocketLabel.length > 0 ? pocketLabel.join('、') : (defalult || '无')
    },
    tagListPocket (value, type, defalult) {
      if (!value) return '无'
      var pocketLabel = []
      const tagList = this.$store.state.tool.pocket.tagList || []
      for (let i = 0; i < tagList.length; i++) {
        const element = tagList[i]
        if (element.shortName === type) {
          if (Array.isArray(value)) {
            for (const item of value) {
              for (const v of element.ch) {
                if (item === v.value) {
                  pocketLabel.push(v.label)
                }
              }
            }
          } else {
            for (const v of i.ch) {
              if (value === v.value) {
                pocketLabel.push(v.label)
              }
            }
          }
          break
        }
      }
      return pocketLabel.length > 0 ? pocketLabel.join('、') : (defalult || '无')
    },
    editHandel (row) {
      this.$store.dispatch('scholarlyLiterature/getDerivationList', { ProjectId: row.projectId }).then(res => {
        this.derivationOptions = res.data
        this.editForm = row
        this.editVisible = true

        this.$refs.editForm && this.$refs.editForm.clearValidate()
      })
    },
    editConfirm () {
      const options = this.editForm
      // options.relation = this.editForm.relationId.map(e => e[1])
      this.$refs.editForm.validate((valid) => {
        if (valid) {
          this.$store.dispatch('scholarlyLiterature/LiteratureEdit', options).then(res => {
            if (res.data) {
              this.editVisible = false
              this.$message.success('编辑成功')
              this.$emit('refreshCurrentPage')
            }
          })
        } else {
          return false
        }
      })
    },
    handleCheckAllChange (val) {
      console.log(val)
      var arr = []
      for (var i = 0; i < this.tableData.length; i++) {
        arr.push(this.tableData[i].literatureId)
      }
      this.checkedCities = val ? arr : []
      this.$emit('change', this.checkedCities)
      this.isIndeterminate = false
    },
    handleCheckedCitiesChange (value) {
      const checkedCount = value.length
      this.checkAll = checkedCount === this.tableData.length
      this.isIndeterminate = checkedCount > 0 && checkedCount < this.tableData.length
      this.$emit('change', value)
    },
    downloadConfirm () {
      this.$refs.downloadForm.validate((valid) => {
        if (valid) {
          const options = {
            ...this.downloadForm,
            LiteratureId: this.selectLiteratureId
          }
          this.$store.dispatch('scholarlyLiterature/GetLiteratureDownloadUrl', options).then(res => {
            downloadByUrl(res.data.url)
            this.downloadVisible = false
            this.downloadForm = {
              Goals: 'DoctorNeeds',
              DoctorNo: undefined,
              ProjectId: undefined
            }
          })
        } else {
          return false
        }
      })
    },
    deleItem (literatureId) {
      this.$confirm('确定删除吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$store.dispatch('scholarlyLiterature/LiteratureDel', { literatureId }).then(res => {
          if (res.data) {
            this.$message.success('删除成功')
            this.$emit('refreshCurrentPage')
          }
        })
      }).catch(() => {})
    },
    addselectLiteratureId (row) {
      console.log(row)
      this.$emit('selectliteratureData', row)
    }
  }
}
</script>

<style lang="scss" scoped>
  .mainComponent {
    .tableList {
      ::v-deep .el-checkbox {
        user-select: auto;
        cursor: default;
      }

      .tableItem {
        display: block;
        width: 100%;
        position: relative;

        ::v-deep .el-checkbox__input {
          position: absolute;
          top: 50%;
          margin-top: -23px;
        }

        ::v-deep .el-checkbox__label {
          width: 100%;
          padding-left: 23px;

          .itemPart {
            border-bottom: 1px solid #ededed;
            padding: 10px 0px;

            .TopPart {
              display: flex;
              justify-content: space-between;
              align-items: center;
              margin-bottom: 10px;

              .TopLeft {
                display: flex;
                align-items: center;

                .topLeftCheck {
                  padding-right: 20px;
                  display: flex;
                }

                .title {
                  cursor: pointer;
                }

                .centerTitle {
                  font-size: 16px;
                  font-weight: 600;
                  padding-right: 15px;
                  color: #333;
                }

                .centerNumber {
                  display: inline-block;
                  width: 130px;
                  height: 17px;
                  font-weight: 600;
                  background-color: rgb(242, 242, 243);
                  border-color: rgb(155, 157, 163);
                  border-width: 1px;
                  border-style: solid;
                  color: rgb(133, 136, 142);
                  border-radius: 3px;
                  font-size: 12px;
                  padding: 0px;
                  text-align: center;
                  line-height: 17px;
                }

                .centerTime {
                  color: #9999;
                  font-size: 14px;
                  line-height: 28px;
                }
              }

              .topRight {
                color: #6666;
                font-size: 14px;
                padding-right: 50px;

                .iconFont {
                  cursor: pointer;
                  color: #60a4e7;

                  &.el-icon-download {
                    color: #67C23A;
                  }

                  &.el-icon-delete {
                    color: orange;
                  }
                }
              }
            }

            .BottomText {
              display: flex;
              justify-content: space-between;
              align-items: center;
              padding-right: 50px;
              color: #636363;
              font-size: 14px;

              .text-tag {
                min-width: 1000px;
                white-space: normal;
                word-break: break-all;
                word-wrap: break-word;
                white-space: pre-wrap;
                line-height: 1.5;
                margin-right: 35px;
              }

              &.noPadding {
                padding-left: 0;
                padding-right: 0;
              }
            }
          }
        }
      }
    }
  }

  ::v-deep .edit-form {
    .MyInputNumber {
      width: 200px;
    }
  }
</style>

2-父组件引入子组件LiteratureTable 如下:

<template>
  <section>
    <el-form :inline="true" class="communication-form" :model="formData">
      <el-form-item>
        <SelectGeneric
          :select.sync="formData.ProjectId"
          :options="'allProject' | pocketOptions"
          placeholder="请选择项目"
          filterable
        >
        </SelectGeneric>
      </el-form-item>
      <el-form-item>
        <SelectGeneric
          :select.sync="formData.derivationId"
          :options="'derivation' | pocketOptions"
          placeholder="请选择出处"
          filterable
        >
        </SelectGeneric>
      </el-form-item>
      <el-form-item>
        <el-date-picker
          v-model="formData.PublishYear"
          :picker-options="pickerOptions"
          value-format="yyyy"
          type="year"
          placeholder="选择年限">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-date-picker
          v-model="formData.Date"
          type="daterange"
          format="yyyy-MM-dd"
          value-format="yyyy-MM-dd"
          range-separator="至"
          start-placeholder="更新开始日期"
          end-placeholder="更新结束日期">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-input v-model="formData.Keyword" placeholder="请输入关键字" clearable></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="search('searchForm')">搜索</el-button>
        <DownloadFileForInspection
          v-if="$_has('documentDatabase:download')"
          btnName="下载"
          type="primary"
          :url="'/literature/literature/downloadPackage'"
          :data="{ literatureIds: selectBatchDownloadIds }"
          method="post"
        />
        <el-button type="primary" v-if="$_has('documentDatabase:upload')" @click="addLiterature" style="margin-left: 10px;">上传</el-button>
        <el-button type="primary" v-if="$_has('documentDatabase:create')" @click="creatRequire">新建需求</el-button>
      </el-form-item>
    </el-form>

    <LiteratureTable
      @change="costPlannedAmountChange($event)"
      :tableData="tableData"
      @refreshCurrentPage="search">
    </LiteratureTable>

    <Pagination
      :total="pagination.totalCount"
      :pageSize="pagination.pageSize"
      :pageNumber.sync="pagination.pageNumber"
      @sizeChange="handleSizeChange"
      @currentChange="handleCurrentChange"
      layout="total, sizes, prev, pager, next, jumper"
    >
    </Pagination>
  </section>
</template>

<script>
import { PageSearch } from '@/mixins'
import LiteratureTable from '../components/LiteratureTable'

export default {
  name: 'DocumentDatabase',
  components: { LiteratureTable },
  mixins: [PageSearch],
  data () {
    return {
      cascaderProps: {
        multiple: true,
        emitPath: false,
        checkStrictly: false,
        label: 'label',
        value: 'value',
        children: 'ch'
      },
      formData: {
        ProjectId: '',
        derivationId: '',
        PublishYear: '',
        Date: '',
        Keyword: ''
      },
      tableData: [],
      addLiteratureVisible: false,
      selectBatchDownloadIds: [],
      pickerOptions: {
        disabledDate: (val) => {
          var date = new Date()
          if (val.getFullYear() >= 2010 && val.getFullYear() <= date.getFullYear()) {
            return false
          } else {
            return true
          }
        }
      },
      activeFormItems: [],
      activeFormField: {}
    }
  },
  activated () {
    this.search()
  },
  watch: {
  },
  methods: {
    // 接收selectBatchDownloadIds
    async costPlannedAmountChange (value) {
      this.selectBatchDownloadIds = value
    },

    addLiterature () {
      this.addLiteratureVisible = true
    },

    addLiteratureConfirm () {
      this.$refs.addLiteratureRef.$refs.addLiteratureForm.validate((valid) => {
        if (valid) {
          // console.log(this.$refs.addLiteratureRef.literatureData)
          const options = JSON.parse(JSON.stringify(this.$refs.addLiteratureRef.literatureData.literatureList))
          if (options.length <= 0) return
          // options.forEach(e => {
          //   e.relation = e.relation.map(e => e[1])
          // })
          const fileNameList = options.map(e => e.fileName)

          this.$store.dispatch('scholarlyLiterature/CheckName', { fileNameList }).then(res => {
            if (res.data.length <= 0) {
              // 校验成功
              this.submitFileList(options)
            }
            if (res.data.length > 0) {
              this.$confirm('文献库中已有重复文件:' + res.data[0], '提示', {
                confirmButtonText: '忽略',
                cancelButtonText: '取消',
                type: 'warning'
              }).then(() => {
                this.submitFileList(options)
              }).catch(() => {})
            }
          })
        } else {
          return false
        }
      })
    },

    submitFileList (data) {
      this.$store.dispatch('scholarlyLiterature/UploadLiterature', { literatureList: data }).then(res => {
        if (res.data) {
          this.addLiteratureVisible = false
          this.$message.success('上传成功')
          this.search()

          this.$refs.addLiteratureRef.literatureData.literatureList = []
        }
      })
    },

    addLiteratureClose () {
      this.addLiteratureVisible = false
      this.$refs.addLiteratureRef.literatureData.literatureList = []
    },

    creatRequire () {
      this.$router.push({ name: 'CreatRequire' })
    },

    literatureRetrieval () {
      this.$router.push({ name: 'LiteratureRetrieval' })
    },

    search (type) {
      if (type === 'searchForm') {
        this.pagination.pageNumber = 1
      }
      const { pageSize, pageNumber } = this.pagination
      const options = {
        ...this.formData,
        // Relation: this.formData.Relation.map(e => e[1]),
        StartTime: this.formData.Date && this.formData.Date[0],
        EndTime: this.formData.Date && this.formData.Date[1],
        pageSize,
        pageNumber
      }
      this.$store.dispatch('scholarlyLiterature/GetLiteratureList', options).then(res => {
        const { list, page } = res.data
        this.tableData = list
        this.pagination = page
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.el-alert {
  margin-bottom: 20px;
}
</style>

你可能感兴趣的:(前端,vue.js)