【sgTransfer】自定义组件:带有翻页、页码、分页器的穿梭框组件,支持大批量数据的穿梭显示。

news/2024/11/14 12:10:34/

 

特性: 

  1. 表格宽度可以自定义
  2. 翻页器显示控件可以自定义
  3. 列配置项可以设置显示字段列名称、宽度、字段名
  4. 可以配置搜索框提示文本,支持搜索过滤
  5. 穿梭框顶部标题可以自定义
  6. 左右箭头按钮文本可以设置

sgTransfer源码

<template><div :class="$options.name"><div class="sg-start " :style="{ width: width }"><div class="sg-title" v-if="titles">{{ titles[0] }}</div><div class="sg-search"><el-input style="width: 100%;" v-model.trim="inputSearchValue_start" maxlength="20" :show-word-limit="false":placeholder="filterPlaceholder || `请输入搜索内容...`" clearable @keyup.native.enter="initListStart"@clear="initListStart"><el-button slot="append" icon="el-icon-search" @click="initListStart" /></el-input></div><div class="sg-table"><el-table ref="table_start" :data="tableData_start" :header-cell-style="{ background: '#f5f7fa' }":height="'300px'" style="width: 100%" stripe @selection-change="selection_start_change":row-class-name="row_class_name" @row-click="row_click_start"><el-table-column type="selection" minWidth="50" :selectable="selectable" /><el-table-column v-for="(a, i) in tableItems_start" :key="i" :prop="a.prop" :label="a.label":width="a.width || false" :minWidth="a.minWidth || false" show-overflow-tooltip /></el-table></div><div class="sg-pagination"><el-pagination background :hidden="startPage.total <= 10" :layout="layout" :page-sizes="[10, 20, 50]":pager-count="5" :current-page.sync="startPage.currentPage" :page-size.sync="startPage.pageSize":total="startPage.total" @size-change="pageChange" @current-change="pageChange" /></div></div><div class="sg-center "><el-button :disabled="disabledLeftButton" @click="remove" type="primary" icon="el-icon-arrow-left">{{buttonTexts ? buttonTexts[0] : ''}}</el-button><el-button :disabled="disabledRightButton" @click="add" type="primary">{{ buttonTexts ? buttonTexts[1] : '' }}<iclass="el-icon-arrow-right" style="margin-left: 5px;"></i></el-button></div><div class="sg-end " :style="{ width: width }"><div class="sg-title" v-if="titles">{{ titles[1] }}</div><div class="sg-search"><el-input style="width: 100%;" v-model.trim="inputSearchValue_end" maxlength="20" :show-word-limit="false":placeholder="filterPlaceholder || `请输入搜索内容...`" clearable@keyup.native.enter="initListEnd({ currentPage: 1 })" @clear="initListEnd"><el-button slot="append" icon="el-icon-search" @click="initListEnd({ currentPage: 1 })" /></el-input></div><div class="sg-table"><el-table ref="table_end" :data="tableData_end" :header-cell-style="{ background: '#f5f7fa' }":height="'300px'" style="width: 100%" stripe @selection-change="selection_end_change"@row-click="row_click_end"><el-table-column type="selection" minWidth="50" /><el-table-column v-for="(a, i) in tableItems_end" :key="i" :prop="a.prop" :label="a.label":width="a.width || false" :minWidth="a.minWidth || false" show-overflow-tooltip /></el-table></div><div class="sg-pagination"><el-pagination background :hidden="endPage.total <= 10" :layout="layout" :page-sizes="[10, 20, 50]":pager-count="5" :current-page.sync="endPage.currentPage" :page-size.sync="endPage.pageSize":total="endPage.total" @size-change="initListEnd" @current-change="initListEnd" /></div></div></div>
</template><script>
export default {name: 'sgTransfer',data() {return {width: '200px',layout: `total, sizes, prev, pager, next, jumper`,disabledForm: false,inputSearchValue_start: '',inputSearchValue_end: '',tableItems_start: [],//表格列配置项tableItems_end: [],//表格列配置项tableData_start: [],//呈现的当前页数据tableData_end: [],//呈现的当前页数据tableData_end_bk: [],//最终选择的数据selection_start: [],selection_end: [],startPage: { currentPage: 1, pageSize: 10, total: 0, },endPage: { currentPage: 1, pageSize: 10, total: 0, },mainKey: null,//主键}},props: ["value","data",/*格式说明data: {width: '400px',//表格宽度layout: `total, sizes, prev, next, jumper`,//翻页器显示控件// 列配置项tableItems: [{ prop: 'ID', label: '工号', minWidth: '50' },{ prop: 'XM', label: '姓名', minWidth: '50' },{ prop: 'YHM', label: '用户名', minWidth: '50' },],tableData: [],//表格显示内容startPage: { total: 0, },//实际总数}, */"titles","buttonTexts","filterPlaceholder",],computed: {disabledLeftButton(d) {return this.selection_end.length === 0;},disabledRightButton(d) {// 在左边表格选中项里面,遍历每一项,如果在右侧表格中都能找到匹配项就truereturn this.selection_start.every(row => this.tableData_end_bk.some(v => this.isSameItem(v, row)));},},watch: {value: {handler(d) {this.inputSearchValue_start = '';this.inputSearchValue_end = '';this.startPage.currentPage = 1;this.endPage.currentPage = 1;this.tableData_end_bk = d || [];this.initListStart();}, deep: true, immediate: true,},data: {handler(d) {if (d) {d.width && (this.width = d.width);d.layout && (this.layout = d.layout);this.tableData_start = d.tableData;this.tableItems_start = d.tableItems_start || d.tableItems;this.tableItems_end = d.tableItems_end || d.tableItems;this.mainKey = (this.tableItems_start.find(v => v.mainKey) || {}).prop;//主键this.startPage.total = (d.startPage || {}).total || 0;}}, deep: true, immediate: true,},tableData_end_bk: {handler(d) {this.$emit(`input`, d);this.initListEnd();if (this.tableData_end.length === 0) {this.inputSearchValue_end = '';this.endPage.currentPage = Math.round(this.tableData_end_bk.length / this.endPage.pageSize);}}, deep: true, immediate: true,},},methods: {row_click_start(row, column, event) { this.$refs.table_start.toggleRowSelection(row); },row_click_end(row, column, event) { this.$refs.table_end.toggleRowSelection(row); },pageChange(d) { this.initListStart(); this.$nextTick(() => { this.refreshCheckStatus() }); },refreshCheckStatus() {this.tableData_start.forEach(row => this.$refs.table_start.toggleRowSelection(row, this.tableData_end_bk.some(v => this.isSameItem(v, row))));},selectable(row) { return !this.tableData_end_bk.some(v => this.isSameItem(v, row)); },row_class_name({ row, rowIndex }) { return this.tableData_end_bk.find(v => this.isSameItem(v, row)) ? 'selected' : ''; },isSameItem(a_obj, b_obj) {let isSame = true;if (this.mainKey) {isSame = a_obj[this.mainKey] == b_obj[this.mainKey];} else {isSame = Object.keys(a_obj).every(k => a_obj[k] == b_obj[k]);}return isSame;},remove(d) {if (this.mainKey) {let selection_end_mainKeys = this.selection_end.map(v => v[this.mainKey]);this.tableData_end_bk = this.tableData_end_bk.filter(v => !selection_end_mainKeys.includes(v[this.mainKey]));} else {let selection_end = this.selection_end.map(v => JSON.stringify(v));this.tableData_end_bk = this.tableData_end_bk.filter(v => !selection_end.includes(JSON.stringify(v)));}this.$nextTick(() => { this.refreshCheckStatus() });},add(d) {this.selection_start.forEach(row => this.tableData_end_bk.some(v => this.isSameItem(v, row)) || this.tableData_end_bk.push(row));},selection_start_change(selection) {this.selection_start = selection;},selection_end_change(selection) {this.selection_end = selection;},initListStart() {this.$emit('init', {keyword: this.inputSearchValue_start,currentPage: this.startPage.currentPage || 1,pageSize: this.startPage.pageSize,});},initListEnd({keyword = this.inputSearchValue_end,currentPage = this.endPage.currentPage || 1,pageSize = this.endPage.pageSize,} = {}) {this.endPage.currentPage = currentPage;this.endPage.pageSize = pageSize;let results = this.tableData_end_bk.filter(obj =>keyword ?Object.keys(obj).some(k => obj[k].toString().toLocaleLowerCase().includes(keyword.toString().toLocaleLowerCase())): true);this.endPage.total = results.length;this.tableData_end = results.slice((currentPage - 1) * pageSize, (currentPage) * pageSize);},},
};
</script><style lang="scss" scoped>
.sgTransfer {display: flex;align-items: center;flex-wrap: nowrap;white-space: nowrap;&>.sg-start,&>.sg-end {border: 1px solid #ebeef5;border-radius: 4px;overflow: hidden;background: #fff;display: inline-block;vertical-align: middle;max-height: 100%;box-sizing: border-box;position: relative;.sg-title {height: 40px;line-height: 40px;background: #f5f7fa;margin: 0;padding-left: 15px;border-bottom: 1px solid #ebeef5;box-sizing: border-box;color: #000;}.sg-search {box-sizing: border-box;padding: 10px;}.sg-table {}.sg-pagination {height: 50px;display: flex;justify-content: center;width: 100%;box-sizing: border-box;padding: 10px;}}&>.sg-center {margin: 0 10px;}&>.sg-end {}
}>>>.el-table {tr.selected {filter: brightness(0.95);pointer-events: none;}.el-table__cell.gutter {border-bottom: 1px solid #EBEEF5;background-color: #f5f7fa;}
}
</style>

用例

<template><div><sgTransfer v-model="transferValue" :data="transferData" :titles="['所有用户', '本组成员']" :button-texts="['到左边', '到右边']":filter-placeholder="`请输入工号、姓名…`" @init="initTransfer" /><hr><div><h1>勾选的数据transferValue:</h1><div v-html="JSON.stringify(transferValue).replace(/\,\{/g, ',\n{')"style="word-wrap: break-word;word-break: break-all;white-space: break-spaces;"> </div></div></div>
</template><script>
import sgTransfer from "@/vue/components/admin/sgTransfer";export default {components: { sgTransfer },data() {return {// 穿梭框配置项transferValue: [],transferData: {width: '400px',//表格宽度layout: `total, sizes, prev, next, jumper`,//翻页器显示控件// 列配置项tableItems: [{ prop: 'ID', label: '工号', minWidth: '50', mainKey: true },//设置主键{ prop: 'XM', label: '姓名', minWidth: '50' },{ prop: 'YHM', label: '用户名', minWidth: '50' },],tableData: [],//表格显示内容startPage: { total: 0, },//实际总数},// 渲染数据tableData: [],tableData_bk: [],userList: [{ key: 1, label: '梁冰露' },{ key: 2, label: '吴梵听' },{ key: 3, label: '卢令美' },{ key: 4, label: '韩宛曼' },{ key: 5, label: '郝海冬' },{ key: 6, label: '傅优悦' },{ key: 7, label: '郝幻莲' },{ key: 8, label: '江嘉云' },{ key: 9, label: '梁秋芳' },{ key: 10, label: '郝悦颖' },{ key: 11, label: '廖芝蓉' },{ key: 12, label: '胡傲丝' },{ key: 13, label: '赵珺琦' },{ key: 14, label: '石心诺' },{ key: 15, label: '丁翠芙' },{ key: 16, label: '李夏河' },{ key: 17, label: '范水悦' },{ key: 18, label: '郑凝雪' },{ key: 19, label: '李亦玉' },{ key: 20, label: '袁三春' },{ key: 21, label: '赵红叶' },{ key: 22, label: '曹安琪' },{ key: 23, label: '谭琴音' },{ key: 24, label: '钟湛蓝' },{ key: 25, label: '陆之柔' },{ key: 26, label: '吕孒凡' },{ key: 27, label: '熊野雪' },{ key: 28, label: '曹叶澜' },{ key: 29, label: '韩粟梅' },{ key: 30, label: '孔杏儿' },{ key: 31, label: '宋若彤' },{ key: 32, label: '于淼淼' },{ key: 33, label: '潘欣跃' },{ key: 34, label: '石雅辰' },{ key: 35, label: '白念珍' },{ key: 36, label: '文爱茹' },{ key: 37, label: '王如曼' },{ key: 38, label: '宋丝琪' },{ key: 39, label: '王凝荷' },{ key: 40, label: '郑雨雪' },{ key: 41, label: '梁映阳' },{ key: 42, label: '徐新雨' },{ key: 43, label: '毛恬雅' },{ key: 44, label: '侯若蕊' },{ key: 45, label: '杨云蔚' },{ key: 46, label: '史之卉' },{ key: 47, label: '胡千束' },{ key: 48, label: '冯冷荷' },{ key: 49, label: '金语心' },{ key: 50, label: '江恬默' },{ key: 51, label: '高香馨' },{ key: 52, label: '江凌晴' },{ key: 53, label: '梁列琴' },{ key: 54, label: '邹鸾瑶' },{ key: 55, label: '夏素洁' },{ key: 56, label: '范秋玉' },{ key: 57, label: '钟北嘉' },{ key: 58, label: '谭水云' },{ key: 59, label: '顾山柏' },{ key: 60, label: '龙曼蔓' },{ key: 61, label: '钟双儿' },{ key: 62, label: '林林娜' },{ key: 63, label: '邹溪儿' },{ key: 64, label: '顾妙彤' },{ key: 65, label: '傅茵茵' },{ key: 66, label: '卢念露' },{ key: 67, label: '罗冷亦' },{ key: 68, label: '胡秋颖' },{ key: 69, label: '姜怡月' },{ key: 70, label: '傅和暄' },{ key: 71, label: '赖布凡' },{ key: 72, label: '郝念蕾' },{ key: 73, label: '邱天欣' },{ key: 74, label: '汤莉莉' },{ key: 75, label: '段靖易' },{ key: 76, label: '周之云' },{ key: 77, label: '董映秋' },{ key: 78, label: '汤玲琅' },{ key: 79, label: '田雁梅' },{ key: 80, label: '石雨雪' },{ key: 81, label: '任君雅' },{ key: 82, label: '蔡小谷' },{ key: 83, label: '孟忆之' },{ key: 84, label: '姜闲丽' },{ key: 85, label: '文忆香' },{ key: 86, label: '戴运虹' },{ key: 87, label: '王玄穆' },{ key: 88, label: '刘绿柳' },{ key: 89, label: '萧梦丝' },{ key: 90, label: '谭忆山' },{ key: 91, label: '方榕嫣' },{ key: 92, label: '徐欣合' },{ key: 93, label: '夏雨南' },{ key: 94, label: '尹沙羽' },{ key: 95, label: '万梦玉' },{ key: 96, label: '谢灵枫' },{ key: 97, label: '曾源源' },{ key: 98, label: '赖谷枫' },{ key: 99, label: '彭子童' },],}},created() {this.createTableData()},methods: {// 初始化、翻页、切换每页显示数量的时候触发initTransfer({ keyword = '', currentPage = 1, pageSize = 10 } = {}) {// 模拟接口调用----------------------------------------let results = this.tableData_bk.filter(obj => keyword ? Object.keys(obj).some(k => obj[k].toString().toLocaleLowerCase().includes(keyword.toString().toLocaleLowerCase())) : true);this.transferData.startPage.total = results.length;this.transferData.tableData = results.slice((currentPage - 1) * pageSize, (currentPage) * pageSize);// ----------------------------------------},// 构建数据createTableData(d) {this.tableData_bk = this.userList.map(v => {let ID = this.$g.getRandomID();return { ID, XM: v.label, YHM: `user${ID}`, }});this.initTransfer();},}
}
</script>


http://www.ppmy.cn/news/1084347.html

相关文章

【大数据实训】基于Hive的北京市天气系统分析报告(二)

博主介绍&#xff1a;✌全网粉丝6W,csdn特邀作者、博客专家、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于大数据技术领域和毕业项目实战✌ &#x1f345;文末获取项目联系&#x1f345; 目录 1. 引言 1.1 项目背景 1 1.2 项目意义 1 2.…

Mac安装Dart时,Homebrew报错 Error: Failure while executing

前言&#xff1a; 最近准备开发Flutter项目时&#xff0c;在安装环境时&#xff0c;安装Homebew时遇到了以下报错信息&#xff0c;在这里分享一下。 报错信息&#xff1a; ~ % brew tap dart-lang/dart > Tapping dart-lang/dart Cloning into /opt/homebrew/Library/Tap…

Prometheus-Rules(规则)

文章目录 一、介绍二、配置 Prometheus 使用规则文件三、 规则文件语法规则文件语法全局Recording rules(记录规则)2 Alerting rules(警报规则)3 模板化如何使用四、检查规则文件语法五、发送警报通知一、介绍 Prometheus规则是一种逻辑表达式,可用于定义有关监控数据的逻…

1921. 消灭怪物的最大数量

原题地址 解法一 排序贪心即可。思想为先计算出每一个怪兽到达城市的时间&#xff0c;然后排序&#xff0c;有小到大进行消灭&#xff0c;此时的下标可视作时间。当怪兽到达城市的时间超过或等于当前时间时&#xff0c;即已经到达了城市&#xff0c;游戏失败&#xff0c;下标…

8月琐碎但值得的事情

8月份结束了&#xff0c;最近心态比较好&#xff0c;慢点就慢点&#xff0c;没有那么着急了&#xff0c;可能是因为着急也没啥办法&#xff0c; 8月是比较开心的一个月&#xff0c;可能是做的事情更有盼头了&#xff0c;可能是看了喜欢的书&#xff0c;可能是我变瘦了&#xff…

03-使用一个不可变对象作为key,红黑树怎么比较大小?

使用一个不可变对象作为key&#xff0c;红黑树怎么比较大小&#xff1f; 答&#xff1a;Java 中的红黑树是通过左旋、右旋的方式来维护树的平衡性&#xff0c;而左旋、右旋又依赖于节点大小的比较。对于使用不可变对象作为key实际上是可以的&#xff0c;因为比较key的大小本身…

c++入门一

参考&#xff1a;https://www.learncpp.com/cpp-tutorial/ When you finish, you will not only know how to program in C, you will know how NOT to program in C, which is arguably as important. Tired or unhappy programmers make mistakes, and debugging code tends…

【小沐学Python】UML类图的箭头连线关系总结(python+graphviz)

文章目录 1、简介1.1 类图1.2 Graphviz 2、Graphviz2.1 安装2.2 命令行测试2.3 python测试 3、关系3.1 实现3.2 泛化3.3 关联3.4 依赖3.5 聚合3.6 组合 结语 1、简介 UML&#xff08;unified modeling language&#xff0c;统一建模语言&#xff09;是一种常用的面向对象设计的…