feat: 表格字段列排序可选组件

This commit is contained in:
TsMask
2023-11-25 15:28:04 +08:00
parent 03a3899377
commit 133affa551

View File

@@ -0,0 +1,156 @@
<script setup lang="ts">
import { reactive, watch, computed } from 'vue';
import { Container, Draggable } from 'vue3-smooth-dnd';
import useI18n from '@/hooks/useI18n';
import { type ColumnsType } from 'ant-design-vue/lib/table';
const { t } = useI18n();
const emit = defineEmits(['update:columns-dnd']);
const props = defineProps({
/**表格字段列,必传 */
columns: {
type: Array<any>,
required: true,
},
});
/**表格字段列 */
const tableColumns = reactive<ColumnsType>(props.columns);
/**表格字段列勾选状态 */
const state = reactive({
indeterminate: true,
checkAll: false,
columnsTitleList: tableColumns.map(s => `${s.title}`),
});
/**表格字段列全选操作 */
function fnTableColumnsCheckAllChange(e: any) {
const checked = e.target.checked;
state.indeterminate = false;
state.columnsTitleList = checked ? tableColumns.map(s => `${s.title}`) : [];
}
/**表格字段列拖拽操作 */
function fnTableColumnsDrop(dropResult: any) {
const { removedIndex, addedIndex, payload } = dropResult;
if (removedIndex !== null && addedIndex !== null) {
let itemToAdd = payload;
itemToAdd = tableColumns.splice(removedIndex, 1)[0];
tableColumns.splice(addedIndex, 0, itemToAdd);
}
}
/**表格字段列固定操作 */
function fnTableColumnsFixed(row: Record<string, any>) {
if (row.fixed === undefined) {
return;
}
const optTitle = t('common.operate');
if (row.title === optTitle) {
const optFixed = row.fixed === 'right';
row.fixed = optFixed ? false : 'right';
} else {
row.fixed = !row.fixed;
}
}
/**表格字段列勾选监听 */
watch(
() => state.columnsTitleList,
val => {
const len = val.length;
state.indeterminate = !!len && len < tableColumns.length;
state.checkAll = len === tableColumns.length;
}
);
/**表格字段列勾选字段变化 */
const tableColumnsCheckList = computed(() => {
let list = tableColumns.filter(s =>
state.columnsTitleList.includes(`${s.title}`)
);
// 取消全选时留最后一个
if (list.length === 0) {
list = [tableColumns[tableColumns.length - 1]];
}
return list;
});
emit('update:columns-dnd', tableColumnsCheckList);
</script>
<template>
<a-tooltip>
<template #title>
{{ t('common.columnSetText') }}
</template>
<a-popover trigger="click" placement="bottomRight">
<template #title>
<div class="table-column-setting-title">
<a-checkbox
v-model:checked="state.checkAll"
:indeterminate="state.indeterminate"
@change="fnTableColumnsCheckAllChange"
>
{{ t('common.columnSetTitle') }}
</a-checkbox>
</div>
</template>
<template #content>
<a-checkbox-group
v-model:value="state.columnsTitleList"
style="width: 100%"
>
<Container orientation="vertical" @drop="fnTableColumnsDrop">
<Draggable v-for="c in tableColumns" :key="c.title">
<div class="table-column-setting-list-item">
<HolderOutlined class="anticon" />
<a-checkbox :value="c.title">
{{ c.title }}
</a-checkbox>
<a-button
v-if="c.fixed !== undefined"
size="small"
:type="c.fixed ? 'primary' : 'dashed'"
@click="fnTableColumnsFixed(c)"
>
<template #icon><FlagOutlined /></template>
</a-button>
</div>
</Draggable>
</Container>
</a-checkbox-group>
</template>
<a-button type="text">
<template #icon><TableOutlined /></template>
</a-button>
</a-popover>
</a-tooltip>
</template>
<style lang="less" scoped>
.table-column-setting-title {
display: flex;
align-items: center;
justify-content: space-between;
height: 32px;
margin-left: 4px;
}
.table-column-setting-list-item {
display: flex;
align-items: center;
width: 100%;
padding: 4px;
}
.table-column-setting-list-item > .anticon {
padding-right: 8px;
cursor: move;
}
.table-column-setting-list-item .ant-checkbox-wrapper {
flex: 1;
margin: 0;
}
</style>