• vue+element之一个table为载体的穿梭框


    有个类似穿梭框的弹窗需求,看了下element-ui的Transfer组件,和原型查了很多。所以自己写了一个,原型图如下:

    image

    估计也没人看,直接放源码防止以后遇到同样需求:

    <template>
      <div class="select-people">
        <div class="left">
          <div class="title-box">
            <span class="tit">待选人员</span>
            <el-input
              style=" 280px"
              placeholder="搜索人员姓名"
              v-model="params.realName"
              class="input-with-select"
            >
              <el-button
                @click="getTeacher(true)"
                slot="append"
                icon="el-icon-search"
              ></el-button>
            </el-input>
          </div>
          <div class="b-cont">
            <div class="l-tree">
              <el-tree
                ref="tree"
                @node-click="checkChange"
                check-on-click-node
                :props="props"
                :load="loadNode"
                highlight-current
                node-key="id"
                lazy
              >
              </el-tree>
            </div>
            <div class="r-table">
              <el-table
                row-class-name="row-cn"
                header-row-class-name="no-bg"
                s
                :data="tableData"
              >
                <el-table-column type="index" width="50" label="序号">
                </el-table-column>
                <el-table-column show-overflow-tooltip prop="realName" label="姓名">
                </el-table-column>
                <el-table-column
                  show-overflow-tooltip
                  width="140"
                  prop="serialNo"
                  label="学工号"
                >
                </el-table-column>
                <el-table-column label="操作">
                  <template slot-scope="scope">
                    <el-button
                      type="text"
                      :disabled="
                        scope.row.selected || (scope.row.status === 1 && multi)
                      "
                      :class="
                        scope.row.selected || (scope.row.status === 1 && multi)
                          ? 'txt-info'
                          : 'txt-primary'
                      "
                      @click="addPeople(scope.row)"
                      >添加</el-button
                    >
                  </template>
                </el-table-column>
              </el-table>
              <div class="page-box">
                <el-pagination
                  @current-change="pageChange"
                  layout="prev, pager, next"
                  :total="total"
                >
                </el-pagination>
              </div>
            </div>
          </div>
        </div>
        <div class="right">
          <div class="title-box">已选人员({{ allSelectedData.length }})</div>
          <div class="b-table">
            <el-table
              row-class-name="row-cn"
              header-row-class-name="no-bg"
              :data="selectedData"
            >
              <el-table-column type="index" width="50" label="序号">
              </el-table-column>
              <el-table-column show-overflow-tooltip prop="realName" label="姓名">
              </el-table-column>
              <el-table-column
                show-overflow-tooltip
                width="120"
                prop="serialNo"
                label="学工号"
              >
              </el-table-column>
              <el-table-column label="操作">
                <template slot-scope="scope">
                  <el-button
                    type="text"
                    class="txt-danger"
                    @click="delPeople(scope)"
                    >删除</el-button
                  >
                </template>
              </el-table-column>
            </el-table>
            <div class="page-box">
              <el-pagination
                @current-change="selectedPageChange"
                layout="prev, pager, next"
                :total="selectedTotal"
              >
              </el-pagination>
            </div>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import {
      getTreeData,
      getTeacherList,
      getCTeacherOrManagerList,
    } from "@/api/application/school-manage.js";
    
    export default {
      props: {
        multi: {
          default: true,
        },
        url: {
          default: "",
        },
      },
      data() {
        return {
          props: {
            label: "name",
            children: "children",
          },
          tableData: [],
          allSelectedData: [],
          selectedData: [],
          selectedTotal: 0,
          selectedCurrentPage: 1,
          total: 0,
          params: {
            id: "",
            pageNo: 1,
            pageSize: 10,
            realName: "",
          },
        };
      },
      methods: {
        async loadNode(node, resolve) {
          const data = node?.data || { id: 0 };
          console.log("one time");
          const { id } = data;
          if (node.level === 0) {
            const child = await this.handleGetTreeData(id);
            child.unshift({
              id: "all",
              name: "全部",
              leaf: true,
            });
            return resolve(child);
          }
          if (node.level === 1) {
            console.log("node", node);
            if (node.data.id === "all") {
              this.handleAllClick();
              return resolve([]);
            } else {
              const child = await this.handleGetTreeData(id);
              return resolve(child);
            }
          } else if (node.level === 2) {
            this.params.pageNo = 1;
            const child = await this.handleGetTreeData(id, true);
            return resolve(child);
          } else {
            resolve([]);
          }
        },
        pageChange(v) {
          this.params.pageNo = v;
          this.getTeacher();
        },
        addPeople(row) {
          {
            // 判断是否多选
            if (!this.multi && this.allSelectedData.length >= 1) {
              this.$message({
                message: "学工管理员只能选择一个",
                type: "warning",
              });
              return;
            }
          }
          row.selected = true;
          this.allSelectedData.push({
            ...row,
            selected: false,
          });
          this.selectedTotal = this.allSelectedData.length;
          this.getCurrentPageSelected();
        },
        // 用于截取指定页数的已选择数据
        getCurrentPageSelected() {
          const allSelectedData = JSON.parse(JSON.stringify(this.allSelectedData));
          this.selectedData = allSelectedData.splice(
            (this.selectedCurrentPage - 1) * 10,
            10
          );
        },
        delPeople(scope) {
          const { $index, row } = scope;
          const { serialNo } = row;
          this.allSelectedData.splice($index, 1);
          // 判断已搜索的人员是否包含删除的这条
          const i = this.tableData.findIndex((e) => e.serialNo === serialNo);
          if (i >= 0) {
            this.tableData[i].selected = false;
          }
          this.selectedTotal = this.allSelectedData.length;
          // 若删除以后所有已选择的数据长度小于等于10,则直接将所有已选数据复制给当前页的已选择数据
          if (this.selectedTotal <= 10) {
            this.selectedData = this.allSelectedData.slice();
            // 如果所有已选数据长度小于等于10,但是已选表格的pageNo大于1时,将pageNo置为1
            if (this.selectedCurrentPage > 1) {
              this.selectedCurrentPage = 1;
            }
          } else {
            // 如果当前已选择的页码pageNo与所有的已选择数据长度/10不一致时,将其减1再执行数据截取操作
            if (this.selectedCurrentPage > Math.ceil(this.selectedTotal / 10)) {
              this.selectedCurrentPage = this.selectedCurrentPage - 1;
            }
            this.getCurrentPageSelected();
          }
        },
        async handleGetTreeData(pid, leaf) {
          const res = await getTreeData({ id: pid });
          const data = res?.data;
          if (!leaf) leaf = false;
          return data.map((e) => {
            const { name, id } = e;
            return {
              name,
              id,
              leaf,
            };
          });
        },
        checkChange(v) {
          const { id } = v;
          if (id === "all") return;
          this.params.id = id;
          this.getTeacher();
        },
        // 获取教师列表
        getTeacher() {
          this.tableData = [];
          // 处理一下已经选择的
          const selectedSerialNo = this.allSelectedData.map((e) => e.serialNo);
          getCTeacherOrManagerList(this.params, this.url).then((res) => {
            const data = res?.data || {};
            this.total = data.total;
            const realD = data?.data || [];
            this.tableData = realD.map((e) => {
              return {
                ...e,
                selected: false,
              };
            });
            this.tableData.forEach((e) => {
              if (selectedSerialNo.indexOf(e.serialNo) >= 0) {
                e.selected = true;
              }
            });
          });
        },
        // 已选择的改变
        selectedPageChange(v) {
          this.selectedCurrentPage = v;
          this.getCurrentPageSelected();
        },
        handleAllClick() {
          this.params.id = "";
          this.params.realName = "";
          this.params.pageNo = 1;
          this.getTeacher();
        },
        clear() {
          this.allSelectedData = [];
          this.selectedData = [];
          this.selectedTotal = 0;
          this.tableData = [];
          this.total = 0;
          this.params.pageNo = 1;
          this.params.realName = "";
          this.params.id = "";
          this.selectedCurrentPage = 1;
          this.$refs.tree.setCurrentKey(null);
        },
      },
    };
    </script>
    
    <style lang="scss">
    .select-people {
      height: 504px;
      display: flex;
      justify-content: space-between;
      .left {
         580px;
        .title-box {
          justify-content: space-between;
        }
        .b-cont {
          display: flex;
          justify-content: space-between;
          height: calc(100% - 50px);
          border: 1px solid rgba(228, 231, 237, 1);
          border-top: none;
          > div {
            height: 100%;
          }
          .l-tree {
             230px;
            border-right: 1px solid rgba(228, 231, 237, 1);
            overflow-y: auto;
          }
          .r-table {
             350px;
            position: relative;
          }
        }
      }
      .page-box {
        display: flex;
        align-items: center;
        height: 39px;
        flex-direction: row-reverse;
        position: absolute;
         100%;
        bottom: 0;
      }
      .right {
         336px;
        .b-table {
          height: calc(100% - 50px);
          border: 1px solid rgba(228, 231, 237, 1);
          border-top: none;
          position: relative;
        }
      }
      .title-box {
        font-size: 16px;
        border: 1px solid rgba(228, 231, 237, 1);
        color: rgba(48, 49, 51, 1);
        display: flex;
        align-items: center;
        height: 50px;
        background-color: rgba(245, 247, 250, 1);
        padding: 0 14px;
      }
      .no-bg {
        th {
          background-color: white;
        }
      }
      .row-cn {
        td {
          padding: 0;
          height: 36px;
        }
      }
      .txt-info {
        color: rgba(235, 238, 245, 1);
      }
      .txt-danger {
        color: #f56c6c;
      }
      .txt-primary {
        color: #409eff;
      }
    }
    </style>
    
    
  • 相关阅读:
    最大回文子串
    找出不含重复字符的最长子串的长度
    链表表示的2个数相加
    如何胜任一个小型公司的技术总监?我的感想
    React 的坑
    MobX 学习
    摘要
    AI 帮助涂鸦
    计算机的前世今生
    常用编辑器实用技巧(pycharm、sublimeText、vim、vscode、Jupyter)
  • 原文地址:https://www.cnblogs.com/codexlx/p/16409213.html
Copyright © 2020-2023  润新知