【transfer 自定义封装穿梭框-适用用手机端】
tag组件
<!--多选按钮组-->
<template>
<div>
<div v-for="option in options" :key="option.value" class='check_style'>
<van-button
:size="size"
:disabled="disabledType ? disabled : option.disabled"
:type="selectedOptions.includes(option.value) ? 'info' : 'default'"
@click.prevent="selectOption(option.value)"
>
{{ option.text }}
</van-button>
</div>
</div>
</template>
<script>
export default {
/**
*** 作者: Lenovo-【Lindon】
*** 文件名称: CheckBtn
*** 文件创建日期: 2023/5/3 9:49
***
*/
name: 'CheckBtn',
props: {
options: {
type: Array,
default: () => []
},
defaultValue: {
type: Array,
default: () => []
},
disabled: {
type: Boolean,
default: false
},
value: {
type: Array,
default: () => []
},
disabledType: {
type: Boolean,
default: true,
},
size: {
type: String,
default: 'small',
}
},
model: {
prop: 'value', // props接受的变量名称
event: 'change', //定义一个方法
},
data() {
return {
selectedOptions: []
}
},
mounted() {
debugger
// 设置初始选中的选项
if (this.defaultValue.length > 0) {
debugger
this.selectedOptions = this.defaultValue
}
},
methods: {
selectOption(value) {
debugger
// 切换选中状态
const index = this.selectedOptions.indexOf(value)
if (index === -1) {
this.selectedOptions.push(value)
} else {
this.selectedOptions.splice(index, 1)
}
// 触发选中事件
// this.$emit('select', this.selectedOptions)
this.$emit('change', this.selectedOptions)
}
}
}
</script>
<style scoped>
.check_style {
display: inline-block;
margin:5px;
}
</style>
穿梭组件
<template>
<div class="vant-transfer">
<div class="transfer-left" :style="{width: leftWidth}">
<div class="left-header">
<div>
<van-checkbox v-model="checkedLeftAll" :disabled="leftCheckboxDisabled" icon-size="16px" shape="square" @change="changeLeftAll" />
</div>
<div class="header_box">
<div>{{ lfetTitle }}</div>
<div style="color: #0084ff">
{{ leftData && leftData.length ? leftData.length : 0 }}/{{ leftOptionsData && leftOptionsData.length ? leftOptionsData.length : 0 }}
</div>
</div>
</div>
<CheckBtn
:propsdef="props"
ref="leftCheckBtn"
style="padding: 0 20px"
size="mini"
:disabled-type="false"
:options="leftOptionsData"
:default-value="selectedOptions"
@change="btnLeftChooes"
/>
</div>
<div style="text-align: center">
<van-button :disabled="rightDisabled" icon="arrow-left" @click="rightSelect" />
<van-button :disabled="leftDisabled" icon="arrow" @click="leftSelect" />
</div>
<div class="transfer-left" :style="{width: rightWidth}">
<div class="left-header">
<div>
<van-checkbox v-model="checkedRightAll" :disabled="rightCheckboxDisabled" icon-size="16px" shape="square" @change="changeRightAll" />
</div>
<div class="header_box">
<div>{{ rightTitle }}</div>
<div style="color: #0084ff">
{{ rightData && rightData.length ? rightData.length : 0 }}/{{ rightOptionsData && rightOptionsData.length ? rightOptionsData.length : 0 }}
</div>
</div>
</div>
<CheckBtn
:propsdef="props"
ref="rightCheckBtn"
style="padding: 0 20px"
size="mini"
:disabled-type="false"
:options="rightOptionsData"
:default-value="selectedOptions"
@change="btnrightChooes"
/>
</div>
</div>
</template>
<script>
import CheckBtn from '@/components/from/CheckBtn.vue';
export default {
name: 'VantTransfer',
components: {
CheckBtn,
},
props: {
data: {
type: Array,
default: () => [],
},
value: {
type: Array,
default: () => [],
},
rightDisabled: {
type: Boolean,
default: true,
},
leftDisabled: {
type: Boolean,
default: true,
},
leftWidth: {
type: String,
default: '30%',
},
rightWidth: {
type: String,
default: '30%',
},
lfetTitle: {
type: String,
default: '列表1',
},
rightTitle: {
type: String,
default: '列表2',
},
},
data() {
return {
props: {
value: 'prcdPrj',
text: 'label',
},
leftOptionsData: [],
rightOptionsData: [],
selectedOptions: [],
leftData: [],
rightData: [],
checkedLeftAll: false,
checkedRightAll: false,
rightCheckboxDisabled: false,
leftCheckboxDisabled: false,
};
},
computed: {},
model: {
prop: 'value', // props接受的变量名称
event: 'change', //定义一个方法
},
mounted() {
this.getOptionsData();
},
watch: {
/* value: function (res) {
this.getOptionsData();
},*/
},
methods: {
reundata(){
let data =[]
this.rightOptionsData.forEach(item=>{
data.push(item[this.props.value])
})
this.$emit('change',data)
},
getOptionsData() {
this.leftOptionsData = [];
this.rightOptionsData = [];
this.data.forEach(item => {
let jsonData = this.value.find(item2 => {
return item.prcdPrj === item2;
});
if (jsonData === undefined) {
this.leftOptionsData.push(item);
} else {
this.rightOptionsData.push(item);
}
});
},
btnLeftChooes(left) {
debugger;
const arr = left.filter(res => {
return res !== undefined;
});
this.leftData = Array.from(arr);
this.leftData.length > 0 ? (this.leftDisabled = false) : (this.leftDisabled = true);
// this.$emit('leftEmit', left);
},
btnrightChooes(right) {
const arr = right.filter(res => {
return res !== undefined;
});
this.rightData = Array.from(arr);
this.rightData.length > 0 ? (this.rightDisabled = false) : (this.rightDisabled = true);
// this.$emit('rightEmit', Array.from(right));
},
leftSelect() {
debugger;
if (this.leftData.length === 0) return this.$toast('请先选择左边的选项');
const leftDataSet = new Set(this.leftData);
const newRightOptionsData = this.leftOptionsData.filter(f => leftDataSet.has(f[this.props['value']]));
this.rightOptionsData = [...this.rightOptionsData, ...newRightOptionsData];
this.leftOptionsData = this.leftOptionsData.filter(f => !leftDataSet.has(f[this.props['value']]));
this.$refs.leftCheckBtn.selectedOptions = [];
this.leftData = [];
this.$refs.leftCheckBtn.selectOption();
this.checkedLeftAll = false;
this.reundata()
},
rightSelect() {
debugger;
if (this.rightData.length === 0) return this.$toast('请先选择右边的选项');
const rightDataSet = new Set(this.rightData);
const newLeftOptionsData = this.rightOptionsData.filter(f => rightDataSet.has(f[this.props['value']]));
this.leftOptionsData = [...this.leftOptionsData, ...newLeftOptionsData];
this.rightOptionsData = this.rightOptionsData.filter(f => !rightDataSet.has(f[this.props['value']]));
this.$refs.rightCheckBtn.selectedOptions = [];
this.rightData = [];
this.$refs.rightCheckBtn.selectOption();
this.checkedRightAll = false;
this.reundata()
},
changeLeftAll(leftAll) {
debugger;
console.log(leftAll);
this.$refs.leftCheckBtn.selectedOptions = [];
this.leftData = [];
if (leftAll) {
const leftOptionsData = this.leftOptionsData.filter(f => !f.disabled);
leftOptionsData.forEach(item => {
this.$refs.leftCheckBtn.selectOption(item[this.props['value']]);
});
} else {
this.$refs.leftCheckBtn.selectOption();
}
},
changeRightAll(rightAll) {
debugger;
this.$refs.rightCheckBtn.selectedOptions = [];
this.rightData = [];
if (rightAll) {
const rightOptionsData = this.rightOptionsData.filter(f => !f.disabled);
rightOptionsData.forEach(item => {
this.$refs.rightCheckBtn.selectOption(item[this.props['value']]);
});
} else {
this.$refs.rightCheckBtn.selectOption();
}
},
},
};
</script>
<style scoped>
.vant-transfer {
display: flex;
align-items: center;
justify-content: center;
}
.transfer-left {
min-height: 100px;
border: 1px solid #dcdada;
border-radius: 4px;
padding: 10px;
margin: 10px;
overflow: scroll;
}
.left-header {
display: flex;
min-width: 100px;
align-items: center;
justify-content: space-between;
background: #dcdada;
padding: 5px;
}
.header_box {
width: 100%;
display: flex;
justify-content: space-evenly;
align-items: center;
padding: 0 0 0 8px;
}
</style>
使用示例
<template>
<div>
<transfer lfet-title='交付店面' right-title='销售店面' :data="form.jcPaymentOrgList" v-model='form.jcPaymentOrgListData' ></transfer>
</div>
</template>
<script>
import transfer from './components/transfer.vue';
export default {
components: {
transfer,
},
data() {
return {
rightOptions: [],
options: [
{
cashierOrgId: 7
createTime: 1705571947
createUser: "4921"
enabled: true
id: 1528
jcOrderNo: "JC-20240118-0001"
prcdPrj: 3
updateTime: 1705906489
updateUser: "4921"
},
{
cashierOrgId: 7
createTime: 1705571947
createUser: "4921"
enabled: true
id: 1528
jcOrderNo: "JC-20240118-0001"
prcdPrj: 3
updateTime: 1705906489
updateUser: "4921"
},
{
cashierOrgId: 7
createTime: 1705571947
createUser: "4921"
enabled: true
id: 1528
jcOrderNo: "JC-20240118-0001"
prcdPrj: 3
updateTime: 1705906489
updateUser: "4921"
},
{
cashierOrgId: 7
createTime: 1705571947
createUser: "4921"
enabled: true
id: 1528
jcOrderNo: "JC-20240118-0001"
prcdPrj: 3
updateTime: 1705906489
updateUser: "4921"
},
{
cashierOrgId: 7
createTime: 1705571947
createUser: "4921"
enabled: true
id: 1528
jcOrderNo: "JC-20240118-0001"
prcdPrj: 3
updateTime: 1705906489
updateUser: "4921"
},
{
cashierOrgId: 7
createTime: 1705571947
createUser: "4921"
enabled: true
id: 1528
jcOrderNo: "JC-20240118-0001"
prcdPrj: 3
updateTime: 1705906489
updateUser: "4921"
},
{
cashierOrgId: 7
createTime: 1705571947
createUser: "4921"
enabled: true
id: 1528
jcOrderNo: "JC-20240118-0001"
prcdPrj: 3
updateTime: 1705906489
updateUser: "4921"
},
{
cashierOrgId: 7
createTime: 1705571947
createUser: "4921"
enabled: true
id: 1528
jcOrderNo: "JC-20240118-0001"
prcdPrj: 3
updateTime: 1705906489
updateUser: "4921"
},
{
cashierOrgId: 7
createTime: 1705571947
createUser: "4921"
enabled: true
id: 1528
jcOrderNo: "JC-20240118-0001"
prcdPrj: 3
updateTime: 1705906489
updateUser: "4921"
},
],
};
},
methods: {
},
};
</script>