layui/.svn/pristine/d4/d4740365ac26061d827cff6e21e796c7e462ef0b.svn-base
2022-12-09 16:41:41 +08:00

312 lines
8.0 KiB
Plaintext

<script lang="ts">
export default {
name: "LayTransfer",
};
</script>
<script setup lang="ts">
import "./index.less";
import LayInput from "../input/index.vue";
import LayButton from "../button/index.vue";
import LayCheckbox from "../checkbox/index.vue";
import { computed, Ref, ref, useSlots, watch } from "vue";
import { BooleanOrString, Recordable } from "../../types";
export interface TransferProps {
id?: string;
title?: string[];
width?: string;
height?: string;
showSearch?: BooleanOrString;
dataSource: Recordable[];
modelValue?: Recordable[];
}
const slots = useSlots();
const props = withDefaults(defineProps<TransferProps>(), {
id: "id",
title: () => ["主列表", "副列表"],
dataSource: () => [],
showSearch: false,
modelValue: () => [],
width: "200px",
height: "360px",
});
const emits = defineEmits(["update:modelValue", "change"]);
const leftDataSource: Ref<any[]> = ref([]);
const rightDataSource: Ref<any[]> = ref([]);
const _leftDataSource: Ref<any[]> = ref([]);
const _rightDataSource: Ref<any[]> = ref([]);
const leftSelectedKeys: Ref<string[]> = ref([]);
const rightSelectedKeys: Ref<string[]> = ref([]);
const allLeftChecked = ref(false);
const allRightChecked = ref(false);
const hasLeftChecked = ref(false);
const hasRightChecked = ref(false);
const allLeftChange = (isChecked: boolean) => {
if (isChecked) {
const datasources = leftDataSource.value.filter((item: any) => {
return !item.disabled;
});
const ids = datasources.map((item) => {
return item[props.id];
});
leftSelectedKeys.value = [...ids];
} else {
leftSelectedKeys.value = [];
}
};
watch(
() => [props.modelValue, props.dataSource],
() => {
let targetDataSource: any[] = [];
props.dataSource.forEach((ds) => {
if (props.modelValue.includes(ds[props.id])) {
targetDataSource.push(ds);
}
});
leftDataSource.value = props.dataSource.filter(
(item) => !props.modelValue.includes(item[props.id])
);
_leftDataSource.value = props.dataSource.filter(
(item) => !props.modelValue.includes(item[props.id])
);
rightDataSource.value = [...targetDataSource];
_rightDataSource.value = [...targetDataSource];
},
{ immediate: true }
);
watch(
leftSelectedKeys,
() => {
if (
leftDataSource.value.length === leftSelectedKeys.value.length &&
leftDataSource.value.length != 0
) {
allLeftChecked.value = true;
} else {
allLeftChecked.value = false;
}
if (leftSelectedKeys.value.length > 0 && leftDataSource.value.length != 0) {
hasLeftChecked.value = true;
} else {
hasLeftChecked.value = false;
}
},
{ deep: true }
);
const allRightChange = (checked: any) => {
if (checked) {
const datasources = rightDataSource.value.filter((item: any) => {
return !item.disabled;
});
const ids = datasources.map((item) => {
return item[props.id];
});
rightSelectedKeys.value = [...ids];
} else {
rightSelectedKeys.value = [];
}
};
watch(
rightSelectedKeys,
() => {
if (
rightDataSource.value.length === rightSelectedKeys.value.length &&
rightDataSource.value.length > 0
) {
allRightChecked.value = true;
} else {
allRightChecked.value = false;
}
if (
rightSelectedKeys.value.length > 0 &&
rightDataSource.value.length != 0
) {
hasRightChecked.value = true;
} else {
hasRightChecked.value = false;
}
},
{ deep: true }
);
const add = () => {
if (leftSelectedKeys.value.length === 0) {
return;
}
let targetKeys: any[] = [];
leftDataSource.value.forEach((item) => {
if (leftSelectedKeys.value.indexOf(item[props.id]) != -1) {
targetKeys.push(item[props.id]);
}
});
rightDataSource.value.forEach((item) => {
targetKeys.push(item[props.id]);
});
emits("change", targetKeys);
emits("update:modelValue", targetKeys);
leftSelectedKeys.value = [];
};
const remove = () => {
if (rightSelectedKeys.value.length === 0) {
return;
}
let targetKeys: any[] = [];
rightDataSource.value.forEach((item) => {
if (rightSelectedKeys.value.indexOf(item[props.id]) == -1) {
targetKeys.push(item[props.id]);
}
});
emits("change", targetKeys);
emits("update:modelValue", targetKeys);
rightSelectedKeys.value = [];
};
const searchLeft = (e: any) => {
if (e === "") {
leftDataSource.value = _leftDataSource.value;
}
leftDataSource.value = _leftDataSource.value.filter((item) => {
if (item.title.indexOf(e) != -1) {
return item;
}
});
};
const searchRight = (e: any) => {
if (e === "") {
rightDataSource.value = _rightDataSource.value;
}
rightDataSource.value = _rightDataSource.value.filter((item) => {
if (item.title.indexOf(e) != -1) {
return item;
}
});
};
const boxStyle = computed(() => {
return {
width: props.width,
height: props.height,
};
});
</script>
<template>
<div>
<div class="layui-transfer layui-form layui-border-box">
<div class="layui-transfer-box" :style="boxStyle">
<div class="layui-transfer-header">
<LayCheckbox
v-model="hasLeftChecked"
:is-indeterminate="!allLeftChecked"
skin="primary"
value="all"
@change="allLeftChange"
>
{{ title[0] }}
</LayCheckbox>
</div>
<div class="layui-transfer-search" v-if="showSearch">
<lay-input
prefix-icon="layui-icon-search"
@input="searchLeft"
placeholder="关键词搜索"
></lay-input>
</div>
<ul class="layui-transfer-data">
<li v-for="dataSource in leftDataSource" :key="dataSource">
<LayCheckbox
v-model="leftSelectedKeys"
skin="primary"
:disabled="dataSource.disabled"
:value="dataSource[id]"
>
<slot v-if="slots.item" name="item" :data="dataSource"></slot>
<template v-else>{{ dataSource.title }}</template>
</LayCheckbox>
</li>
</ul>
<div class="layui-transfer-footer" v-if="slots.leftFooter">
<slot name="leftFooter"></slot>
</div>
</div>
<div class="layui-transfer-active">
<div class="layui-transfer-button-group">
<LayButton
type="primary"
:disabled="leftSelectedKeys.length == 0"
@click="add"
><i class="layui-icon layui-icon-next"></i
></LayButton>
<LayButton
type="primary"
:disabled="rightSelectedKeys.length == 0"
@click="remove"
><i class="layui-icon layui-icon-prev"></i
></LayButton>
</div>
</div>
<div class="layui-transfer-box" :style="boxStyle">
<div class="layui-transfer-header">
<LayCheckbox
v-model="hasRightChecked"
:is-indeterminate="!allRightChecked"
skin="primary"
value="all"
@change="allRightChange"
>
{{ title[1] }}
</LayCheckbox>
</div>
<div class="layui-transfer-search" v-if="showSearch">
<lay-input
prefix-icon="layui-icon-search"
@input="searchRight"
placeholder="关键词搜索"
></lay-input>
</div>
<ul class="layui-transfer-data">
<li v-for="dataSource in rightDataSource" :key="dataSource">
<LayCheckbox
skin="primary"
v-model="rightSelectedKeys"
:disabled="dataSource.disabled"
:value="dataSource[id]"
>
<slot v-if="slots.item" name="item" :data="dataSource"></slot>
<template v-else>{{ dataSource.title }}</template>
</LayCheckbox>
</li>
</ul>
<div class="layui-transfer-footer" v-if="slots.rightFooter">
<slot name="rightFooter"></slot>
</div>
</div>
</div>
</div>
</template>