feat: 表格字段列排序可选组件
This commit is contained in:
156
src/components/TableColumnsDnd/index.vue
Normal file
156
src/components/TableColumnsDnd/index.vue
Normal 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>
|
||||
Reference in New Issue
Block a user