1.由于列表数据过多,上千甚至上万条数据,如果全部加载,页面交互很卡
2.官方搜索不支持异步调接口查询,所以需要自定义搜索
3.切换页码,调接口获取数据后,右侧上一页已选择的数据会没办法回显,所以需要把上一页的数据合并到接口返回数据里面
4.回显数据,选的可能不是当前页的数据,所以需要把已选择的数据合并到接口返回数据里面,并根据指定字段去重
5.默认的宽高太小,需要通过css设置穿梭框的宽高
<template>
<el-dialog v-model="dialogVisible" title="选择项目" width="50%" append-to-body
:close-on-click-modal="false" @close="cancel">
<!-- filterable :filter-method="filterMethod"-->
<el-form :inline="true">
<el-form-item prop="searchQuery" style="margin-right: 10px">
<el-input
v-model="searchQuery"
placeholder="请输入搜索内容"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getXmList">搜索</el-button>
</el-form-item>
</el-form>
<el-transfer
v-loading="transferLoading"
class="custom-transfer"
v-model="transferValue"
:titles="['可选项目', '已选项目']"
filter-placeholder="请输入"
:data="displayedData"
:props="{ key: 'code', label: 'name' }"
@change="handleChange"
:render-content="renderContent"
>
<template #left-footer>
<el-pagination
:current-page="currentPage"
:page-size="pageSize"
:total="total"
@current-change="handleCurrentChange"
layout="prev, pager, next"
:pager-count="5"
/>
</template>
</el-transfer>
<template #footer v-if="!disabled">
<div class="dialog-footer">
<el-button type="primary" @click="confirm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup name="transfer">
import {getBaseData} from '@/api/api';
const emit = defineEmits(['selectCompleted']);
const dialogVisible = ref(false)
const disabled = ref(false)
const transferValue = ref([])//code数组
const selectedArr = ref([])//选中的数组对象
const displayedData = ref([])
const currentData = ref({})
const transferLoading = ref(false)
const total = ref(0)
const currentPage = ref(1)
const pageSize=ref(500)
/**切换页码-获取项目列表*/
const handleCurrentChange = (val) => {
currentPage.value = val;
getXmList()
}
const searchQuery = ref('')
/**选中值*/
const handleChange = (targetKeys) => {
console.log('选中的值',targetKeys)
selectedArr.value = displayedData.value.filter(item => transferValue.value.includes(item.code))
}
const filterMethod = (query, item) => {
return item.name.indexOf(query) > -1
}
/**打开弹窗*/
const openDialog = (params = {}) => {
let {checkedData = []} = params
console.log('默认选中的项目checkedData', checkedData)
currentData.value = params
transferValue.value = checkedData.map(item => item.code)
dialogVisible.value = true
getXmList()
}
/**弹窗-确定事件*/
const confirm = () => {
let {fieldId, qylx, qfType} = currentData.value
let data = {
fieldId: fieldId,
qfType: qfType,
qylx: qylx,
selectedValue: selectedArr.value
}
emit('selectCompleted', data)
cancel()
}
/**取消事件-重置数据*/
const cancel = () => {
dialogVisible.value = false
displayedData.value = []
selectedArr.value = []
transferValue.value = []
searchQuery.value = ''
currentPage.value=1
}
/**(除外疾病type传3,不需要传xmType),除外项目、预授权项目type传2,xmType传1*/
const getXmList = () => {
displayedData.value = []
transferLoading.value = true
let {type, xmType} = currentData.value
let params = {
type: type,
xmType: xmType,
name: searchQuery.value,
pageNum: currentPage.value,
pageSize: pageSize.value
}
getBaseData(params).then(res => {
transferLoading.value = false
if (res.code == 1) {
let {content = [], total: totalNum} = res.data
total.value=totalNum
let {checkedData = []} = currentData.value
let resultData = content || []//后端返回null的时候处理
let newArr = [...checkedData, ...resultData]
displayedData.value = uniqueBy(newArr, 'code')
prePageSelectedData()
}
})
}
const renderContent = (h, option) => {
let content = option.jg ? `${option.name} ¥${option.jg}` : `${option.name}`
return h('span', {style: 'color: #606266;'}, content);
}
/**根据指定字段去重*/
const uniqueBy = (arr, key) => {
const seen = new Set();
return arr.filter((item) => {
const k = item[key];
return seen.has(k) ? false : seen.add(k);
});
}
/**获取上一页右侧选中的数据,把上一页的数据添加到当前页*/
const prePageSelectedData=()=>{
let resultData=[...selectedArr.value,...displayedData.value]
displayedData.value=uniqueBy(resultData,'code')
}
defineExpose({openDialog})
</script>
<style lang="scss">
.custom-transfer {
.el-transfer-panel__list {
height: 500px;
}
.el-transfer-panel {
width: 320px;
&:last-child{
vertical-align: top;
}
}
.el-transfer-panel__body {
height: 500px;
}
.el-pagination{
height: 100%;
}
}
</style>