vue實(shí)現(xiàn)自定義el-table穿梭框功能
一、需求描述
前段時(shí)間接到一個(gè)需求是點(diǎn)擊做一個(gè)類似穿梭框的表格點(diǎn)擊選中功能,彈框的左邊是全部數(shù)據(jù)展示,點(diǎn)擊表格行數(shù)據(jù)可以選中自動(dòng)增加到右邊的已選框,并且可以手動(dòng)刪除、重置選中數(shù)據(jù)。
點(diǎn)擊確定后到展示到主頁(yè)面,被選中的數(shù)據(jù)打開彈框不能再次選擇。
二、界面展示
功能如下圖所示:
主頁(yè)面沒有選中的數(shù)據(jù)時(shí),展示如下:

彈框頁(yè)面,展示如下:

選中后主頁(yè)面的數(shù)據(jù)顯示如下:

再次點(diǎn)擊添加學(xué)生成績(jī)按鈕,之前選中數(shù)據(jù)不可再點(diǎn)擊,如下圖:

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

