vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue自定义el-table穿梭框功能

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

作者:Lemon今天学习了吗

这篇文章主要介绍了vue实现自定义el-table穿梭框功能,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、需求描述

前段时间接到一个需求是点击做一个类似穿梭框的表格点击选中功能,弹框的左边是全部数据展示,点击表格行数据可以选中自动增加到右边的已选框,并且可以手动删除、重置选中数据。

点击确定后到展示到主页面,被选中的数据打开弹框不能再次选择。

二、界面展示

功能如下图所示:

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

弹框页面,展示如下:

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

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

三、代码实现

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>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文