首页 > 其他分享 >vue实现表格穿梭框

vue实现表格穿梭框

时间:2023-05-08 11:22:56浏览次数:41  
标签:vue return 表格 transfer button 穿梭 table border left

新建穿梭组件  bTransfer.vue

  1 <template>
  2   <div class="bpo-table-transfer">
  3     <div class="bpo-table-transfer-panel">
  4       <p class="transfer-panel-header">
  5         <span>{{ titleTexts && titleTexts[0] }}</span>
  6         <span>{{ leftSelection.length }}/{{ slicedData.length }}</span>
  7       </p>
  8       <div class="bpo-table-transfer-left-header">
  9         <slot name="left-header" />
 10       </div>
 11       <el-table ref="leftTable" size="small" :max-height="maxHeight" :height="minHeight" :data="slicedData"
 12         :row-key="rowKey" @selection-change="handleLeftSelectionChange" border stripe>
 13         <el-table-column width="40px" type="selection" />
 14         <slot name="left-table-columns" />
 15       </el-table>
 16       <slot name="left-footer" />
 17     </div>
 18     <div class="bpo-table-transfer-button-tray">
 19       <el-button type="primary" :class="buttonClasses" :disabled="disabledLeftButton" @click="addToRight">
 20         <span v-if="buttonTexts[0] !== undefined" class="button-text">{{ buttonTexts[0] }}</span>
 21         <i class="el-icon-arrow-right"></i>
 22       </el-button>
 23       <el-button type="primary" :class="buttonClasses" :disabled="rightSelection.length === 0" @click="addToLeft">
 24         <i class="el-icon-arrow-left"></i>
 25         <span v-if="buttonTexts[1] !== undefined" class="button-text">{{ buttonTexts[1] }}</span>
 26       </el-button>
 27     </div>
 28     <div class="bpo-table-transfer-panel">
 29       <p class="transfer-panel-header">
 30         <span>{{ titleTexts && titleTexts[1] }}</span>
 31         <span>{{ rightSelection.length }}/{{ valueCopy.length }}</span>
 32       </p>
 33       <div class="bpo-table-transfer-right-header">
 34         <slot name="right-header" />
 35       </div>
 36 
 37       <el-table ref="rightTable" size="small" :max-height="maxHeight" :height="minHeight" :data="valueCopy"
 38         :row-key="rowKey" @selection-change="handleRightSelectionChange" border stripe>
 39         <el-table-column width="40px" type="selection" />
 40         <slot name="right-table-columns" />
 41       </el-table>
 42       <slot name="right-footer">
 43         <el-pagination style="float: right;margin: 5px;" :total="valueCopy.length" layout="total">
 44         </el-pagination>
 45       </slot>
 46     </div>
 47   </div>
 48 </template>
 49 
 50 <script>
 51 import _ from "lodash";  //引用 loadsh
 52 export default {
 53   name: 'BpoEltTransfer',
 54   props: {
 55     value: {
 56       type: Array,
 57       required: true
 58     },
 59     data: {
 60       type: Array,
 61       default() {
 62         return []
 63       }
 64     },
 65     rowKey: {
 66       type: String,
 67       default: 'id'
 68     },
 69     // 标题文本
 70     //TODO: i18n
 71     titleTexts: {
 72       type: Array,
 73       default() {
 74         return ['待选项', '已选项']
 75       }
 76     },
 77     // 按钮文本
 78     buttonTexts: {
 79       type: Array,
 80       default() {
 81         return []
 82       }
 83     },
 84     // 表格最小高度
 85     minHeight: {
 86       type: String,
 87       default: '300px'
 88     },
 89     // 表格最大高度
 90     maxHeight: {
 91       type: String,
 92       default: '500px'
 93     }
 94   },
 95   data() {
 96     return {
 97       valueCopy: [...this.value],
 98       totalSize: 0,
 99       leftSelection: [],
100       rightSelection: []
101     }
102   },
103   computed: {
104     hasButtonTexts() {
105       return this.buttonTexts.length === 2
106     },
107     buttonClasses() {
108       return ['transfer-button', { 'is-with-texts': this.hasButtonTexts }]
109     },
110     disabledLeftButton() {
111       return !this.leftSelection.some(leftRow => !this.value.some(rightRow => leftRow[this.rowKey] === rightRow[this.rowKey]))
112     },
113     slicedData() {
114       return this.data.filter(item => !this.valueCopy.some(o => o[this.rowKey] === item[this.rowKey]))
115     }
116   },
117   methods: {
118     handleLeftSelectionChange(selection) {
119       this.leftSelection = selection
120     },
121     handleRightSelectionChange(selection) {
122       this.rightSelection = selection
123     },
124     addToRight() {
125       this.valueCopy.push(...this.leftSelection)
126       this.$emit('input', this.valueCopy)
127 
128     },
129     addToLeft() {
130       //差集 _.xorWith   需要npm install lodash    
131       this.valueCopy = _.xorWith(this.rightSelection, this.valueCopy)
132       this.$emit('input', this.valueCopy)
133       console.log(this.valueCopy)
134     }
135   }
136 }
137 </script>
138 
139 <style scoped>
140 .bpo-table-transfer {
141   font-size: 14px;
142   display: flex;
143   justify-content: center;
144   align-items: center;
145 }
146 
147 .el-icon-arrow-right,
148 .el-icon-arrow-left {
149   font-size: 40px;
150   cursor: pointer;
151 }
152 
153 .bpo-table-transfer-panel {
154   border: 1px solid #EBEEF5;
155   border-radius: 4px;
156   overflow: hidden;
157   background: #FFF;
158   display: inline-block;
159   width: calc((100% - 100px) / 2);
160   max-height: 100%;
161   box-sizing: border-box;
162   position: relative
163 }
164 
165 .bpo-table-transfer-panel .transfer-panel-header {
166   height: 40px;
167   line-height: 40px;
168   background: #F5F7FA;
169   margin: 0;
170   padding-left: 15px;
171   border-bottom: 1px solid #EBEEF5;
172   -webkit-box-sizing: border-box;
173   box-sizing: border-box;
174   color: #000;
175 }
176 
177 .transfer-panel-header span:last-child {
178   position: absolute;
179   right: 15px;
180 }
181 
182 .bpo-table-transfer-button-tray {
183   display: inline-block;
184   vertical-align: middle;
185   width: 100px;
186 }
187 
188 .transfer-button {
189   display: block;
190   margin: 0 auto;
191   padding: 10px;
192   border-radius: 4px;
193   color: #FFF;
194   background-color: #409EFF;
195   font-size: 0;
196 }
197 
198 .transfer-button .button-text {
199   margin-left: 2px;
200   margin-right: 5px;
201 }
202 
203 .transfer-button.is-with-texts {
204   border-radius: 4px;
205 }
206 
207 .transfer-button.is-disabled,
208 .transfer-button.is-disabled:hover {
209   border: 1px solid #DCDFE6;
210   background-color: #F5F7FA;
211   color: #C0C4CC;
212 }
213 
214 .transfer-button:first-child {
215   margin-bottom: 10px;
216 }
217 
218 .transfer-button:nth-child(2) {
219   margin: 0 auto;
220 }
221 
222 .transfer-button i,
223 .transfer-button span {
224   font-size: 14px;
225 }
226 
227 .bpo-table-transfer-left-header {
228   padding: 10px;
229 }
230 .bpo-table-transfer-right-header {
231   padding: 10px;
232 }
233 </style>

 

使用穿梭组件

  1 <template>
  2   <bpo-elt-transfer
  3           :title-texts="['待选择','已选择']"
  4           min-height="300"
  5           max-height="600"
  6           row-key="userId"
  7           :data="pageInfo.list"
  8           v-model="selectedUsers"
  9         >
 10           <template #left-header>
 11             <el-row :gutter="20">
 12               <el-col :span="8"><span>姓名:</span></el-col>
 13               <el-col :span="8"><span>通讯:</span></el-col>
 14 
 15             </el-row>
 16             <el-row :gutter="20">
 17               <el-col :span="8">
 18                 <el-input v-model="searchForm.userName" size="mini" clearable/>
 19               </el-col>
 20               <el-col :span="8">
 21                 <el-input v-model="searchForm.email" size="mini" clearable/>
 22               </el-col>
 23               <el-col :span="5">
 24                 <el-button style="width: 100px" type="primary" size="mini" @click="handleSearch()"><span>检索</span>
 25                 </el-button>
 26               </el-col>
 27             </el-row>
 28           </template>
 29           <template #left-table-columns>
 30             <el-table-column
 31               label="id"
 32               align="left"
 33               prop="userId"
 34               header-align="center"
 35               show-overflow-tooltip
 36               :min-width="100"
 37             />
 38             <el-table-column
 39               :resizable="false"
 40               align="left"
 41               header-align="center"
 42               label="姓名"
 43               prop="userName"
 44               show-overflow-tooltip
 45               min-width="100">
 46             </el-table-column>
 47             <el-table-column
 48               label="通讯"
 49               align="left"
 50               prop="email"
 51               header-align="center"
 52               show-overflow-tooltip
 53               :min-width="100"
 54             />
 55           </template>
 56           <template #left-footer>
 57             <el-pagination style="float: right;margin: 5px;"
 58                            @current-change="handleCurrentChange"
 59                            :current-page="pageInfo.pageNum"
 60                            :page-size="pageInfo.pageSize"
 61                            layout="total, prev, pager, next, jumper"
 62                            :total="pageInfo.total">
 63             </el-pagination>
 64           </template>
 65           <template #right-table-columns>
 66             <el-table-column
 67               label="id"
 68               align="left"
 69               prop="userId"
 70               header-align="center"
 71               show-overflow-tooltip
 72               :min-width="100"
 73             />
 74             <el-table-column
 75               :resizable="false"
 76               align="left"
 77               header-align="center"
 78               label="姓名"
 79               prop="userName"
 80               show-overflow-tooltip
 81               min-width="100">
 82             </el-table-column>
 83             <el-table-column
 84               label="通讯"
 85               align="left"
 86               prop="email"
 87               header-align="center"
 88               show-overflow-tooltip
 89               :min-width="100"
 90             />
 91           </template>
 92         </bpo-elt-transfer>
 93         </template>
 94 
 95         <script>
 96 export default {
 97   name: 'TransferExample',
 98   data() {
 99     return {
100       searchForm: {
101         userName: '',
102         email: ''
103       },
104       selectedUsers: [],
105       pageInfo: {
106         list: [
107     {
108         "userId": "00R43K",
109         "userName": "test4",
110         "email": "[email protected]"
111     },
112     {
113         "userId": "1B5BQY",
114         "userName": "test2",
115         "email": "[email protected]"
116     },
117     {
118         "userId": "4K091Y",
119         "userName": "test3",
120         "email": "[email protected]"
121     },
122     {
123         "userId": "admin",
124         "userName": "Admin",
125         "email": "[email protected]"
126     },
127     {
128         "userId": "demo01",
129         "userName": "Demo01",
130         "email": "[email protected]"
131     },
132     {
133         "userId": "SO1351",
134         "userName": "qwqwq",
135         "email": "[email protected]"
136     }
137 ],
138         pageNum: this.$PAGE_NUM,
139         pageSize: this.$PAGE_SIZE,
140         total: 0
141       }
142     }
143   },
144   methods: {
145     handleSearch(searchCondition) {
146       this.axios.post('/api/available-user', {
147         pageNum: this.$PAGE_NUM,
148         pageSize: this.$PAGE_SIZE,
149         organizationCode: this.userMapping.organizationCode,
150         ...this.searchForm,
151         ...searchCondition
152       })
153         .then(({data}) => {
154           this.pageInfo = data.retResult
155         })
156     },
157     handleCurrentChange(val) {
158       this.handleSearch({
159         pageNum: val,
160         pageSize: this.pageInfo.pageSize
161       })
162     }
163   }
164 }
165 </script>

Attributes

参数说明类型默认值
value / v-model 绑定值 array
data 候选池(左表)的数据源 array []
button-texts 自定义标题文案 array ['待选项', '已选项']
title-texts 自定义按钮文案 array ['','']
min-height 表格最小高度 string 300px
max-height 表格最大高度 string 500px
row-key 表格行数据的Key string id

Slot

名称说明
left-header 自定义左表header
left-footer 自定义左表footer
left-table-columns 左表的列,参照原生el-table-colum 使用
left-header 自定义右表header
left-footer 自定义右表footer, 默认内容为一个右格行数统计
left-table-columns 右表的列,参照原生el-table-colum 使用

 

 

转自:https://github.com/SonicMiso/bpo-elt-transfer

标签:vue,return,表格,transfer,button,穿梭,table,border,left
From: https://www.cnblogs.com/L-hailong/p/17381187.html

相关文章

  • 列表的批量操作组件封装 + 权限 ,如何更优雅的实现呢?Vue3
    这个组件解决的问题?在以往的项目当中,我从未想过要对批量/列表数据的操作按钮做什么变动,直到最近的一次开发,让我突然觉得可以将操作按钮也做成一个公共组件,在做前端开发时,更加专注于js代码逻辑。如何使用?全局(main.js中)引用操作组件BatchOperation.vue创建页面操作按钮act......
  • 一个函数抓取代谢组学权威数据库HMDB的所有表格数据
    爬虫是都不陌生的一个概念,比如百度、谷歌都有自己的爬虫工具去抓取网站、分析、索引,方便我们的查询使用。在我们浏览网站、查询信息时,如果想做一些批量的处理,也可以去分析网站的结构、抓取网页、提取信息,然后就完成了一个小爬虫的写作。网页爬虫需要我们了解URL的结构、HTML语法特......
  • java基于springboot+vue非前后端分离的学生成绩管理系统、学生信息管理系统,附源码+数
    1、项目介绍java基于springboot+vue非前后端分离的学生成绩管理系统、学生信息管理系统。本文首先介绍了学生成绩管理的技术发展背景与发展现状,然后遵循软件常规开发流程,首先针对系统选取适用的语言和开发平台,根据需求分析制定模块并设计数据库结构,再根据系统总体功能模块的设计......
  • Vue.js:Vue-Router动态路由从服务器接口获取路由数据
    (目录)文档https://v3.router.vuejs.org/zh/installation.html版本号"vue":"2.6.10","vue-router":"3.6.5",有几种方式实现动态路由:前端配置完整路由,通过接口返回的数据判断是否可显示,是否可访问前端配置部分路由,由后端接口返回的数据生成新路由抛开路由的思维,是否......
  • element中表格的另一种显示方法
    正常(默认展示该数据的相关属性值):      <el-table-column       prop="name"       label="姓名"       width="180"      ></el-table-column>转换法(去掉prop属性,改为用值判断显示内容):     ......
  • Vue2入门之超详细教程九-监视属性
    1、简介监视属性watch:1.当被监视的属性变化时,回调函数自动调用,进行相关操作2.监视的属性必须存在,才能进行监视!!3.监视的两种写法:(1) newVue时传入watch配置(2) 通过vm.$watch监视深度监测:(1) Vue中的......
  • VueUse 是怎么封装Vue3 Provide/Inject 的?
    Provide/InjectProvide和Inject可以解决Prop逐级透传问题。注入值类型不会使注入保持响应性,但注入一个响应式对象,仍然有响应式的效果。Provide的问题是无法追踪数据的来源,在任意层级都能访问导致数据追踪比较困难,不知道是哪一个层级声明了这个或者不知道哪一层级或若干个......
  • 在vue3中使用elementPlus的el-select时样式穿透问题
    下拉框的option样式只能在全局样式里改,千万不能用scope,否则不生效<el-selectclass="select":popper-append-to-body="false"v-model="selectValue"placeholder="请选择"popper-class="select-option"><......
  • vue2使用图片懒加载之vue-lazyload
    1.为什么要进行图片懒加载呢?使用图片懒加载的主要原因是为了优化网站或应用程序的性能和用户体验。当页面中存在大量图片时,如果一次性全部加载会影响页面的加载速度,用户可能需要等待很长时间才能看到完整的页面内容,这会影响用户的体验和满意度。2.如何实现图片懒加载使用http......
  • 关于vue系统禁止脚本运行问题的解决
    问题描述满怀期待地输入vuelist命令行,然后就出现了这个错误问题解决以管理员身份运行终端界面,在该界面输入get-ExecutionPolicy,查看脚本运行状态是否被允许,若是出现Restricted结果,则表明被禁止;若是出现RemoteSigned结果,则表明没有被禁止;(是可以正常使用的!)若是被禁止,则输入se......