vue 自定义el-table穿梭框功能

40 篇文章 0 订阅

一、需求描述:前段时间接到一个需求是点击做一个类似穿梭框的表格点击选中功能,弹框的左边是全部数据展示,点击表格行数据可以选中自动增加到右边的已选框,并且可以手动删除、重置选中数据。点击确定后到展示到主页面,被选中的数据打开弹框不能再次选择。

二、界面展示:功能如下图所示:

  • 主页面没有选中的数据时,展示如下:

  •  弹框页面,展示如下:

  •  选中后主页面的数据显示如下:

  •  再次点击添加学生成绩按钮,之前选中数据不可再点击,如下图:

 三、代码实现:

  1. 首页面表格主键是orderId ,主页面代码:
    <div class="content-box">
      <div class="table-title flex-between">
        <span>学生成绩信息</span> 
        <div style="text-align:end">
          <el-button plain type="primary" @click="delSomeMedic()">批量删除</el-button>
          <el-button type="primary" @click="addMedic()">添加学生成绩</el-button>
        </div>
      </div>
      <div class="single-table">
        <el-table ref="table" size="mini" height="100%" :data="tableData.adrDrugInfos" :header-cell-style="{background: '#fff',height:'40px'}" border
        @selection-change="handleSelectionChange">
          <el-table-column type="selection" width="40"> </el-table-column>
          <el-table-column prop="dose" label="姓名" show-overflow-tooltip></el-table-column>
          <el-table-column prop="suspectedConcomitant" label="是否住校" show-overflow-tooltip width="100">
            <template #default="scope">
              <span v-if="scope.row.suspectedConcomitant == '1'">住校生</span>
              <span v-if="scope.row.suspectedConcomitant == '2'">非住校生</span>
            </template>
          </el-table-column>
          <el-table-column prop="doseUnit" label="数学" show-overflow-tooltip></el-table-column>
          <el-table-column prop="frequency" label="语文" show-overflow-tooltip></el-table-column>
          <el-table-column prop="routeName" label="英语" show-overflow-tooltip></el-table-column>
          <el-table-column prop="reasonForUse" label="备注" show-overflow-tooltip></el-table-column>
          <el-table-column label="操作" header-align="center" width="200" align="center" fixed="right">
              <template slot-scope="scope">
                <el-button size="small" style="color: #409eff; padding: 0" type="text" @click="editMedic(false,scope.row)">成绩详情</el-button>
                <el-button size="small" style="color: #409eff; padding: 0" type="text" @click="editMedic(true,scope.row)">编辑</el-button>
                <el-button size="small" style="color: #409eff; padding: 0" type="text" @click="delMedic(scope.row)">删除</el-button>
              </template>
            </el-table-column>
        </el-table>
      </div>
    </div>
    
    //-----------------------------------------------------------------------------
    // 新增学生成绩信息
        addMedic() {
          if (this.tableData.healthEventId == '') {
            return this.$message.warning('请先选择学生')
          } else {
            this.$refs.addMedicDialog.open(
              this.tableData.adrDrugInfos,
              this.tableData.healthEventId,
              this.tableData.visitType
            )
          }
        },
        // 删除学生成绩信息
        delMedic(row) {
          this.$Confirm({ type: 'delete' })
            .then((e) => {
              this.tableData.adrDrugInfos.map((item, index) => {
                if (item.orderId == row.orderId) {
                  this.tableData.adrDrugInfos.splice(index, 1)
                  this.$message.success('删除成功!')
                }
              })
            })
            .catch((err) => {
              console.log(err)
            })
        },
    //选中学生成绩信息数据
        handleSelectionChange(val) {
          this.selectedMedicData = val
        },
    // 批量学生成绩信息
        delSomeMedic() {
          if (this.selectedMedicData.length <= 0) {
            return this.$message.warning('请先选择学生成绩信息')
          }
          this.$Confirm({ type: 'delete' })
            .then((e) => {
              this.selectedMedicData.forEach((val) => {
                this.tableData.adrDrugInfos.forEach((v, i) => {
                  if (val.orderId == v.orderId) {
                    this.tableData.adrDrugInfos.splice(i, 1)
                    this.$message.success('删除成功!')
                  }
                })
              })
            })
            .catch((err) => {
              console.log(err)
            })
        },
    // 选择学生成绩信息回显
        getMedicalData(data) {
          data.forEach((item) => {
            this.tableData.adrDrugInfos.push({
              orderId: item.orderId||'',
              suspectedConcomitant: item.suspectedConcomitant||'',
              dose: item.onceDosage||'',
              doseUnit: item.dosageunitName||'',
              frequency: item.freqDesc||'',
              routeName: item.defaultUsageCode||'',
              formName: item.drugForm||'',
              reasonForUse: item.reasonForUse||'',
            })
          })
        },
  2. 弹框页面数据主键是orderId,弹框页面代码:
    <template>
      <el-dialog
        title="添加学生成绩"
        :visible.sync="dialogVisible"
        :close-on-click-modal="false"
        @close="close"
        append-to-body
        top="10vh !important"
        width="90%"
      >
        <div class="box-wrapper">
          <div class="single-table-container left-table">
            <div class="search-form-wrapper">
              <div class="title">学生成绩列表</div>
              <div class="seach_list">
                <el-input
                  prefix-icon="el-icon-search"
                  placeholder="学生姓名"
                  v-model="searchForm.onceDosage"
                  size="mini"
                  clearable
                ></el-input>
                <el-date-picker
                  v-model="dateTime"
                  type="daterange"
                  value-format="yyyy-MM-dd"
                  format="yyyy-MM-dd"
                  range-separator="—"
                  @change="changeDateTime"
                  start-placeholder="在校开始时间"
                  end-placeholder="在校结束时间"
                >
                </el-date-picker>
                <el-button type="primary" size="mini" @click="searchTable"
                  >查询</el-button
                >
              </div>
            </div>
            <div class="single-table">
              <el-table
                ref="leftTable"
                v-loading="tableLoading"
                size="mini"
                height="370px"
                :data="tableData"
                stripe
                row-key="orderId"
                tooltip-effect="dark"
                :header-cell-style="{
                  background: '#f5f7fa',
                  fontWeight: 'bold',
                  color: '#303133'
                }"
                border
                @selection-change="handleSelectionChange"
                @row-click="handleClickTableRow"
              >
                <el-table-column
                  type="selection"
                  width="40"
                  :reserve-selection="true"
                  :selectable="handleSelected"
                ></el-table-column>
                <el-table-column
                  type="index"
                  header-align="center"
                  align="center"
                  label="序号"
                  width="50"
                ></el-table-column>
                <el-table-column
                  prop="onceDosage"
                  label="姓名"
                  show-overflow-tooltip
                  width="120"
                  :formatter="formartTableField"
                ></el-table-column>
                <el-table-column
                  prop="startDateTime"
                  label="在校开始时间"
                  show-overflow-tooltip
                  width="100"
                  :formatter="formartTableField"
                ></el-table-column>
                <el-table-column
                  prop="stopDateTime"
                  label="在校结束时间"
                  show-overflow-tooltip
                  width="100"
                  :formatter="formartTableField"
                ></el-table-column>
                <el-table-column
                  prop="dosageunitName"
                  label="数学"
                  show-overflow-tooltip
                  :formatter="formartTableField"
                ></el-table-column>
                <el-table-column
                  prop="freqDesc"
                  label="语文"
                  show-overflow-tooltip
                  :formatter="formartTableField"
                ></el-table-column>
                <el-table-column
                  prop="defaultUsageCode"
                  label="英语"
                  show-overflow-tooltip
                  :formatter="formartTableField"
                ></el-table-column>
              </el-table>
            </div>
            <div class="table-pagination">
              <el-pagination
                class="pagination"
                @current-change="handleCurrentChange"
                :current-page="pages.pageIndex"
                :page-size="pages.pageSize"
                layout="total,prev, pager, next"
                :total="pages.total"
              ></el-pagination>
            </div>
          </div>
          <div class="single-table-container right-table">
            <div class="search-form-wrapper">
              <div class="title">已选学生</div>
            </div>
            <div class="single-table">
              <el-form
                :model="selectedForm"
                ref="selectedForm"
                :rules="selectedForm.rules"
              >
                <el-table
                  ref="rightTable"
                  size="mini"
                  height="410px"
                  :data="selectedForm.selectedData"
                  stripe
                  tooltip-effect="dark"
                  :header-cell-style="{
                    background: '#f5f7fa',
                    fontWeight: 'bold',
                    color: '#303133'
                  }"
                  border
                >
                  <el-table-column
                    type="index"
                    header-align="center"
                    align="center"
                    label="序号"
                    width="50"
                  ></el-table-column>
                  <el-table-column
                    prop="onceDosage"
                    label="姓名"
                    width="120"
                    show-overflow-tooltip
                  ></el-table-column>
                  <el-table-column
                    label="住校生/非住校生"
                    show-overflow-tooltip
                    width="188"
                  >
                    <template #default="scope">
                      <el-form-item
                        :prop="
                          'selectedData.' + scope.$index + '.suspectedConcomitant'
                        "
                      >
                        <el-radio-group
                          v-model="scope.row.suspectedConcomitant"
                          size="mini"
                        >
                          <el-radio label="1">住校生</el-radio>
                          <el-radio label="2">非住校生</el-radio>
                        </el-radio-group>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column label="选择原因" show-overflow-tooltip>
                    <template #default="scope">
                      <el-form-item
                        :prop="'selectedData.' + scope.$index + '.reasonForUse'"
                        :rules="selectedForm.rules.reasonForUse"
                      >
                        <el-input
                          placeholder="请输入"
                          v-model="scope.row.reasonForUse"
                          clearable
                        ></el-input>
                      </el-form-item>
                    </template>
                  </el-table-column>
                  <el-table-column
                    label="操作"
                    header-align="center"
                    align="center"
                    width="80"
                  >
                    <template slot-scope="scope">
                      <el-button
                        size="small"
                        style="color: #409eff; padding: 0"
                        type="text"
                        @click="del(scope.row)"
                        >删除</el-button
                      >
                    </template>
                  </el-table-column>
                </el-table>
              </el-form>
            </div>
          </div>
        </div>
        <span slot="footer" class="dialog-footer">
          <el-button @click="reset">重置</el-button>
          <el-button :loading="btn_loading" type="primary" @click="submit"
            >确认</el-button
          >
        </span>
      </el-dialog>
    </template>
    <script>
    import { getAdviceRec } from '@/api/adr/report-manage-service'
    
    export default {
      components: {},
      data() {
        return {
          dialogVisible: false,
          tableLoading: false,
          btn_loading: false,
          healthEventId: '',
          visitType: '',
          searchForm: {
            onceDosage: '',
            startDateTime: '',
            stopDateTime: ''
          },
          dateTime: [],
          selectedForm: {
            selectedData: [],
            rules: {
              reasonForUse: [
                { required: true, message: '请输入选中学生的原因', trigger: 'blur' }
              ]
            }
          },
          pages: {
            pageIndex: 1,
            pageSize: 10,
            total: 0
          },
          tableData: [
            {
              orderId: 1,
              onceDosage: '张三',
              startDateTime: '2020-01-01',
              stopDateTime: '2023-01-01',
              dosageunitName: '98',
              freqDesc: '95',
              defaultUsageCode: '99'
            },
            {
              orderId: 2,
              onceDosage: '李四',
              startDateTime: '2020-01-01',
              stopDateTime: '2023-05-01',
              dosageunitName: '100',
              freqDesc: '92',
              defaultUsageCode: '95'
            },
            {
              orderId: 3,
              onceDosage: '王五',
              startDateTime: '2021-01-01',
              stopDateTime: '2023-02-01',
              dosageunitName: '98',
              freqDesc: '95',
              defaultUsageCode: '100'
            },
            {
              orderId: 4,
              onceDosage: '赵六',
              startDateTime: '2021-06-01',
              stopDateTime: '2024-01-01',
              dosageunitName: '98',
              freqDesc: '100',
              defaultUsageCode: '90'
            }
          ],
          pSelectedData: [] // 父级数据
        }
      },
      methods: {
        open(data, healthEventId, visitType) {
          this.healthEventId = healthEventId || ''
          this.visitType = visitType || ''
          this.dialogVisible = true
          if (!!data && data.length > 0) {
            this.pSelectedData = data
          } else {
            this.pSelectedData = []
          }
          this.initTable()
        },
        initTable() {
          this.tableLoading = true
          let params = {
            current: this.pages.pageIndex,
            size: this.pages.pageSize,
            visitType: this.visitType,
            healthEventId: this.healthEventId,
            startDateTime: this.searchForm.startDateTime,
            stopDateTime: this.searchForm.stopDateTime,
            onceDosage: this.searchForm.onceDosage
          }
          params = useKyyDelNullProperty(params)
          getAdviceRec(params)
            .then((res) => {
              if (res.code == 200) {
                this.tableLoading = false
                this.tableData = res.result.records
                this.pages.total = res.result.total
                // 默认在校
                this.tableData.forEach((item) => {
                  this.$set(item, 'suspectedConcomitant', '1')
                })
                // 固定对齐表格
                this.$nextTick(() => {
                  this.$refs.leftTable.doLayout()
                })
              } else {
                this.$message.error(`错误:${res.message}`)
              }
            })
            .catch((err) => {})
          setTimeout(() => {
            this.tableLoading = false
          }, 5000)
        },
        handleSelectionChange(val) {
          this.selectedForm.selectedData = val
        },
        close() {
          this.dialogVisible = false
          this.searchForm.onceDosage = ''
          this.searchForm.startDateTime = ''
          this.searchForm.stopDateTime = ''
          this.reset()
        },
        reset() {
          this.btn_loading = false
          this.$refs.leftTable.clearSelection()
        },
        // 删除
        del(row) {
          // 取消选中
          this.selectedForm.selectedData.map((item, index) => {
            if (item.orderId == row.orderId) {
              this.selectedForm.selectedData.splice(index, 1)
              this.$refs.leftTable.toggleRowSelection(row, false)
            }
          })
        },
        // 点击行勾选数据
        handleClickTableRow(row, event, column) {
          if (!this.handleSelected(row)) return false
          if (this.selectedForm.selectedData.length > 0) {
            // 如果结果数组不为空,判断所选的这条是否在结果数组里
            if (
              JSON.stringify(this.selectedForm.selectedData).indexOf(
                JSON.stringify(row.orderId)
              ) == -1
            ) {
              this.selectedForm.selectedData.push(row)
              this.$refs.leftTable.toggleRowSelection(row, true)
            } else {
              // 取消选中
              this.selectedForm.selectedData.map((item, index) => {
                if (item.orderId == row.orderId) {
                  this.selectedForm.selectedData.splice(index, 1)
                  this.$refs.leftTable.toggleRowSelection(row, false)
                }
              })
            }
          } else {
            this.selectedForm.selectedData.push(row)
            this.$refs.leftTable.toggleRowSelection(row, true)
          }
        },
        // 已选数据不可再选,通过比较orderId 是否一致
        handleSelected(row, index) {
          if (this.pSelectedData?.length > 0) {
            if (
              this.pSelectedData.some((el) => {
                return el.orderId == row.orderId
              })
            ) {
              return false
            } else {
              return true
            }
          } else {
            return true
          }
        },
        submit() {
          this.btn_loading = true
          if (this.selectedForm.selectedData.length > 0) {
            this.$refs.selectedForm.validate(async (valid) => {
              if (valid) {
                this.$emit('getMedicalData', this.selectedForm.selectedData)
                this.close()
                this.$message.success('操作成功')
              } else {
                return this.$message.warning('请输入选择原因')
              }
            })
          } else {
            this.$message.warning('请选择要添加的学生成绩信息')
          }
          this.btn_loading = false
        },
        // 分页栏
        handleCurrentChange(val) {
          this.pages.pageIndex = val
          this.initTable()
        },
        formartTableField(row, column, cellValue, index) {
          if (cellValue) {
            return cellValue
          }
          return '-'
        },
        changeDateTime(data) {
          if (data) {
            this.searchForm.startDateTime = data[0]
            this.searchForm.stopDateTime = data[1]
          } else {
            this.searchForm.startDateTime = ''
            this.searchForm.stopDateTime = ''
          }
        },
        // 查询
        searchTable() {
          if (!!this.dateTime && this.dateTime.length > 0) {
            this.searchForm.startDateTime = this.dateTime[0]
            this.searchForm.stopDateTime = this.dateTime[1]
          }
          this.pages.pageIndex = 1
          this.initTable()
        }
      }
    }
    </script>
    <style lang="scss" scoped>
    .box-wrapper {
      font-size: 14px;
      display: flex;
      justify-content: space-between;
      .left-table {
        width: 51%;
        padding: 0;
      }
      .right-table {
        width: 48%;
        padding: 0;
        .el-input {
          width: 100%;
        }
        .el-form-item {
          margin: 0;
        }
        .el-radio-group {
          :deep(.el-radio) {
            margin-right: 10px;
            .el-radio__label {
              font-size: 12px;
              padding-left: 10px;
            }
          }
        }
      }
    }
    //单页表格
    .single-table-container {
      width: 100%;
      height: 100%;
      padding: 10px;
      overflow: auto;
      .search-form-wrapper {
        height: 40px;
        display: flex;
        align-items: center;
        border: 1px solid #e6eaef;
        border-bottom: none;
        padding: 0 10px;
        .title {
          font-size: 14px;
          font-weight: 700;
          color: #303133;
        }
      }
      .single-table {
        height: calc(100% - 80px);
        .inner_table {
          padding: 10px;
          // background: rgba(25, 137, 254, 0.1);
          margin-top: -4px;
          margin-bottom: -4px;
        }
      }
      .table-pagination {
        text-align: right;
        height: 40px;
        background: #fff;
        border: 1px solid #e6eaef;
        border-top: unset;
        .el-pagination {
          padding: 6px 10px;
        }
      }
    }
    </style>
    

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue.js 是一个流行的JavaScript架,它的数据绑定和组件化特性使得开发动态Web应用变得更加容易。其中,强大的UI组件库(如Element,iView等)能够极大地提高Web应用开发效率。而el-table是一种用于展示表格数据的组件,它拥有可排序、过滤、分页等多种功能。本文主要介绍如何使用Vue.js实现el-table表头自定义。 在Vue.js中使用el-table组件时,表头(thead)用于显示列名和控制排序、过滤等操作。默认情况下,el-table组件根据数据源中的列名自动生成表头。若需自定义表头,可通过以下方式实现: 1. 使用el-table-column组件 在el-table中使用el-table-column组件可以实现自定义表头。具体操作如下: ```html <el-table :data="tableData"> <el-table-column prop="date" label="日期"></el-table-column> <el-table-column prop="name" label="姓名"></el-table-column> <el-table-column prop="address" label="地址"></el-table-column> </el-table> ``` 上述代码中,我们为el-table添加了三个el-table-column组件,分别对应表格中的三列数据。同时,我们在每个el-table-column组件上指定了prop和label属性,其中prop属性指定了对应的数据源中的字段名,label属性指定了表头标题。 2. 使用Scoped Slots 如果需要实现更加复杂的表头,可以使用Scoped Slots进行自定义。具体操作如下: ```html <el-table :data="tableData"> <template slot="header"> <el-row> <el-col :span="8">日期</el-col> <el-col :span="8">姓名</el-col> <el-col :span="8">地址</el-col> </el-row> </template> <el-table-column prop="date"></el-table-column> <el-table-column prop="name"></el-table-column> <el-table-column prop="address"></el-table-column> </el-table> ``` 上述代码中,我们使用了el-table的header slot,它可以让我们自定义表头,即在表头中添加任意HTML代码。在header slot中我们使用了el-row和el-col组件创建了一个表头行,然后通过span属性设置每列所占的宽度,最终实现了自定义表头。 总结 以上就是Vue.js实现el-table表头自定义的两种方式。使用el-table-column组件可以快速地实现简单的自定义表头,而使用Scoped Slots可以实现更加复杂的表头需求。选择合适的方式,可以大大提高开发效率和表格的可读性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值