vue實現(xiàn)自定義el-table穿梭框功能
一、需求描述
前段時間接到一個需求是點擊做一個類似穿梭框的表格點擊選中功能,彈框的左邊是全部數(shù)據(jù)展示,點擊表格行數(shù)據(jù)可以選中自動增加到右邊的已選框,并且可以手動刪除、重置選中數(shù)據(jù)。
點擊確定后到展示到主頁面,被選中的數(shù)據(jù)打開彈框不能再次選擇。
二、界面展示
功能如下圖所示:
主頁面沒有選中的數(shù)據(jù)時,展示如下:
彈框頁面,展示如下:
選中后主頁面的數(shù)據(jù)顯示如下:
再次點擊添加學(xué)生成績按鈕,之前選中數(shù)據(jù)不可再點擊,如下圖:
三、代碼實現(xiàn)
1.首頁面表格主鍵是orderId ,主頁面代碼:
<div class="content-box"> <div class="table-title flex-between"> <span>學(xué)生成績信息</span> <div style="text-align:end"> <el-button plain type="primary" @click="delSomeMedic()">批量刪除</el-button> <el-button type="primary" @click="addMedic()">添加學(xué)生成績</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="數(shù)學(xué)" 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> //----------------------------------------------------------------------------- // 新增學(xué)生成績信息 addMedic() { if (this.tableData.healthEventId == '') { return this.$message.warning('請先選擇學(xué)生') } else { this.$refs.addMedicDialog.open( this.tableData.adrDrugInfos, this.tableData.healthEventId, this.tableData.visitType ) } }, // 刪除學(xué)生成績信息 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) }) }, //選中學(xué)生成績信息數(shù)據(jù) handleSelectionChange(val) { this.selectedMedicData = val }, // 批量學(xué)生成績信息 delSomeMedic() { if (this.selectedMedicData.length <= 0) { return this.$message.warning('請先選擇學(xué)生成績信息') } 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) }) }, // 選擇學(xué)生成績信息回顯 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.彈框頁面數(shù)據(jù)主鍵是orderId,彈框頁面代碼:
<template> <el-dialog title="添加學(xué)生成績" :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">學(xué)生成績列表</div> <div class="seach_list"> <el-input prefix-icon="el-icon-search" placeholder="學(xué)生姓名" 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="在校結(jié)束時間" > </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="在校結(jié)束時間" show-overflow-tooltip width="100" :formatter="formartTableField" ></el-table-column> <el-table-column prop="dosageunitName" label="數(shù)學(xué)" 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">已選學(xué)生</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" >確認(rèn)</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: '請輸入選中學(xué)生的原因', 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: [] // 父級數(shù)據(jù) } }, 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 // 默認(rèn)在校 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) } }) }, // 點擊行勾選數(shù)據(jù) handleClickTableRow(row, event, column) { if (!this.handleSelected(row)) return false if (this.selectedForm.selectedData.length > 0) { // 如果結(jié)果數(shù)組不為空,判斷所選的這條是否在結(jié)果數(shù)組里 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) } }, // 已選數(shù)據(jù)不可再選,通過比較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('請選擇要添加的學(xué)生成績信息') } 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>
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue中如何使用echarts和echarts-gl實現(xiàn)3D餅圖環(huán)形餅圖
現(xiàn)在vue是很多公司前端的主流框架,我目前所在公司接觸的項目也都是使用vue來實現(xiàn)的,很少有完全使用原生的JavaScript來寫項目的了,下面這篇文章主要給大家介紹了關(guān)于vue中如何使用echarts和echarts-gl實現(xiàn)3D餅圖環(huán)形餅圖的相關(guān)資料,需要的朋友可以參考下2023-03-03vue2中,根據(jù)list的id進(jìn)入對應(yīng)的詳情頁并修改title方法
今天小編就為大家分享一篇vue2中,根據(jù)list的id進(jìn)入對應(yīng)的詳情頁并修改title方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08基于Vue3+element-plus實現(xiàn)中英文切換功能
在?Vue?3?項目中結(jié)合?vue-i18n?和?Element?Plus?實現(xiàn)中英文切換是一個常見的需求,下面是一個詳細(xì)的步驟指南,幫助你完成這個任務(wù),需要的朋友可以參考下2024-11-11vue + typescript + video.js實現(xiàn) 流媒體播放 視頻監(jiān)控功能
視頻才用流媒體,有后臺實時返回數(shù)據(jù), 要支持flash播放, 所以需安裝對應(yīng)的flash插件。這篇文章主要介紹了vue + typescript + video.js 流媒體播放 視頻監(jiān)控,需要的朋友可以參考下2019-07-07詳解Vue自定義指令如何實現(xiàn)處理圖片加載失敗的碎圖
這篇文章主要介紹了詳解Vue自定義指令如何實現(xiàn)處理圖片加載失敗的碎圖,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-02-02vue+elementUi中的table實現(xiàn)跨頁多選功能(示例詳解)
最近在開發(fā)工業(yè)品超市的后臺系統(tǒng),遇到一個需求,就是實現(xiàn)在一個table表格中多選數(shù)據(jù),在網(wǎng)上查了好多,有些方法真的是無語,下面通過本文給大家分享vue+elementUi中的table實現(xiàn)跨頁多選功能,感興趣的朋友跟隨小編一起看看吧2024-05-05