feat: ColumnSetting and SizeSetting persist (#3398)

This commit is contained in:
xachary
2023-12-12 12:04:03 +08:00
committed by GitHub
parent 57e6e4f004
commit f4df2d5a4b
7 changed files with 602 additions and 252 deletions

View File

@@ -6,7 +6,7 @@
<Popover
placement="bottomLeft"
trigger="click"
@open-change="handleVisibleChange"
@open-change="onOpenChange"
:overlayClassName="`${prefixCls}__column-list`"
:getPopupContainer="getPopupContainer"
>
@@ -14,25 +14,25 @@
<div :class="`${prefixCls}__popover-title`">
<Checkbox
:indeterminate="indeterminate"
v-model:checked="state.checkAll"
@change="onCheckAllChange"
v-model:checked="isColumnAllSelected"
@change="onColumnAllSelectChange"
>
{{ t('component.table.settingColumnShow') }}
</Checkbox>
<Checkbox v-model:checked="checkIndex" @change="handleIndexCheckChange">
<Checkbox v-model:checked="isIndexColumnShow" @change="onIndexColumnShowChange">
{{ t('component.table.settingIndexColumnShow') }}
</Checkbox>
<!-- 设置了 rowSelection 才出现 -->
<Checkbox
v-model:checked="checkSelect"
@change="handleSelectCheckChange"
:disabled="!defaultRowSelection"
v-model:checked="isRowSelectionShow"
@change="onRowSelectionShowChange"
v-if="defaultIsRowSelectionShow"
>
{{ t('component.table.settingSelectColumnShow') }}
</Checkbox>
<a-button size="small" type="link" @click="reset">
<a-button size="small" type="link" @click="onReset">
{{ t('common.resetText') }}
</a-button>
</div>
@@ -40,12 +40,12 @@
<template #content>
<ScrollContainer>
<Checkbox.Group v-model:value="state.checkedList" @change="onChange" ref="columnListRef">
<template v-for="item in plainOptions" :key="item.value">
<div :class="`${prefixCls}__check-item`" v-if="!('ifShow' in item && !item.ifShow)">
<Checkbox.Group v-model:value="columnCheckedOptions" ref="columnOptionsRef">
<template v-for="opt in columnOptions" :key="opt.value">
<div :class="`${prefixCls}__check-item`" :data-no="opt.value">
<DragOutlined class="table-column-drag-icon" />
<Checkbox :value="item.value">
{{ item.label }}
<Checkbox :value="opt.value">
{{ opt.label }}
</Checkbox>
<Tooltip
@@ -61,11 +61,11 @@
:class="[
`${prefixCls}__fixed-left`,
{
active: item.fixed === 'left',
disabled: !state.checkedList.includes(item.value),
active: opt.fixed === 'left',
disabled: opt.value ? !columnCheckedOptions.includes(opt.value) : true,
},
]"
@click="handleColumnFixed(item, 'left')"
@click="onColumnFixedChange(opt, 'left')"
/>
</Tooltip>
<Divider type="vertical" />
@@ -82,11 +82,11 @@
:class="[
`${prefixCls}__fixed-right`,
{
active: item.fixed === 'right',
disabled: !state.checkedList.includes(item.value),
active: opt.fixed === 'right',
disabled: opt.value ? !columnCheckedOptions.includes(opt.value) : true,
},
]"
@click="handleColumnFixed(item, 'right')"
@click="onColumnFixedChange(opt, 'right')"
/>
</Tooltip>
</div>
@@ -99,302 +99,515 @@
</Tooltip>
</template>
<script lang="ts" setup>
import type { BasicColumn, BasicTableProps, ColumnChangeParam } from '../../types/table';
import { ref, reactive, watchEffect, nextTick, unref, computed, useAttrs } from 'vue';
import type { BasicColumn, ColumnOptionsType, ColumnChangeParam } from '../../types/table';
import { ref, nextTick, unref, computed, useAttrs, watch, onMounted } from 'vue';
import { Tooltip, Popover, Checkbox, Divider } from 'ant-design-vue';
import type {
CheckboxChangeEvent,
CheckboxValueType,
} from 'ant-design-vue/lib/checkbox/interface';
import type { CheckboxChangeEvent } from 'ant-design-vue/lib/checkbox/interface';
import { SettingOutlined, DragOutlined } from '@ant-design/icons-vue';
import Icon from '@/components/Icon/Icon.vue';
import { ScrollContainer } from '@/components/Container';
import { useI18n } from '@/hooks/web/useI18n';
import { useTableContext } from '../../hooks/useTableContext';
import { useDesign } from '@/hooks/web/useDesign';
// import { useSortable } from '@/hooks/web/useSortable';
import { isFunction, isNil } from '@/utils/is';
import { getPopupContainer as getParentContainer } from '@/utils';
import { cloneDeep, omit } from 'lodash-es';
import { cloneDeep } from 'lodash-es';
import Sortablejs from 'sortablejs';
import type Sortable from 'sortablejs';
interface State {
checkAll: boolean;
isInit?: boolean;
checkedList: string[];
defaultCheckList: string[];
}
// 列表设置缓存
import { useTableSettingStore } from '@/store/modules/tableSetting';
import { useRoute } from 'vue-router';
import { TableRowSelection } from '@/components/Table/src/types/table';
interface Options {
label: string;
value: string;
fixed?: boolean | 'left' | 'right';
}
const tableSettingStore = useTableSettingStore();
defineOptions({ name: 'ColumnSetting' });
const emit = defineEmits(['columns-change']);
const attrs = useAttrs();
const route = useRoute();
const { t } = useI18n();
const table = useTableContext();
const defaultRowSelection = omit(table.getRowSelection(), 'selectedRowKeys');
let inited = false;
// 是否当前的setColumns触发的
let isSetColumnsFromThis = false;
// 是否当前组件触发的setProps
let isSetPropsFromThis = false;
const cachePlainOptions = ref<Options[]>([]);
const plainOptions = ref<Options[] | any>([]);
const plainSortOptions = ref<Options[]>([]);
const columnListRef = ref(null);
const state = reactive<State>({
checkAll: true,
checkedList: [],
defaultCheckList: [],
});
/** 缓存初始化props */
let cacheTableProps: Partial<BasicTableProps<any>> = {};
const checkIndex = ref(false);
const checkSelect = ref(false);
const { prefixCls } = useDesign('basic-column-setting');
const getValues = computed(() => {
return unref(table?.getBindValues) || {};
});
const attrs = useAttrs();
const table = useTableContext();
watchEffect(() => {
const columns = table.getColumns();
setTimeout(() => {
if (isSetColumnsFromThis) {
isSetColumnsFromThis = false;
} else if (columns.length) {
init();
}
}, 0);
});
const getPopupContainer = () => {
return isFunction(attrs.getPopupContainer) ? attrs.getPopupContainer() : getParentContainer();
};
watchEffect(() => {
const values = unref(getValues);
if (isSetPropsFromThis) {
isSetPropsFromThis = false;
} else {
cacheTableProps = cloneDeep(values);
// 是否已经从缓存恢复
let isRestored = false;
let isInnerChange = false;
// 列可选项
const columnOptions = ref<ColumnOptionsType[]>([]);
const columnOptionsRef = ref(null);
// 已选列
const columnCheckedOptions = ref<string[]>([]);
// 已选变化
watch(columnCheckedOptions, () => {
// 恢复缓存后生效
if (isRestored) {
// 显示
columnOptions.value
.filter((o) => columnCheckedOptions.value.includes(o.value))
.forEach((o) => {
o.column.defaultHidden = false;
});
// 隐藏
columnOptions.value
.filter((o) => !columnCheckedOptions.value.includes(o.value))
.forEach((o) => {
o.column.defaultHidden = true;
o.fixed = undefined;
});
// 从 列可选项 更新 全选状态
isColumnAllSelectedUpdate();
// 列表列更新
tableColumnsUpdate();
// 更新列缓存
columnOptionsSave();
}
checkIndex.value = !!values.showIndexColumn;
checkSelect.value = !!values.rowSelection;
});
function getColumns() {
const ret: Options[] = [];
table.getColumns({ ignoreIndex: true, ignoreAction: true }).forEach((item) => {
ret.push({
label: (item.title as string) || (item.customTitle as string),
value: (item.dataIndex || item.title) as string,
...item,
});
});
return ret;
}
// 全选
const isColumnAllSelected = ref<boolean>(false);
const onColumnAllSelectChange = () => {
if (columnCheckedOptions.value.length < columnOptions.value.length) {
columnCheckedOptions.value = columnOptions.value.map((o) => o.value);
} else {
columnCheckedOptions.value = [];
}
};
async function init(isReset = false) {
// 半选状态
const indeterminate = computed(() => {
return (
columnCheckedOptions.value.length > 0 &&
columnCheckedOptions.value.length < columnOptions.value.length
);
});
// 是否显示序号列
const isIndexColumnShow = ref<boolean>(false);
// 序号列更新
const onIndexColumnShowChange = (e: CheckboxChangeEvent) => {
// 更新 showIndexColumn
showIndexColumnUpdate(e.target.checked);
// 更新 showIndexColumn 缓存
tableSettingStore.setShowIndexColumn(e.target.checked);
// 从无到有需要处理
if (e.target.checked) {
const columns = cloneDeep(table?.getColumns());
const idx = columns.findIndex((o) => o.flag === 'INDEX');
// 找到序号列
if (idx > -1) {
const cache = columns[idx];
// 强制左fix
cache.fixed = 'left';
// 强制移动到 第一/选择列后
columns.splice(idx, 1);
columns.splice(0, 0, cache);
// 设置列表列
tableColumnsSet(columns);
}
}
};
// 是否显示选择列
const isRowSelectionShow = ref<boolean>(false);
// 选择列更新
const onRowSelectionShowChange = (e: CheckboxChangeEvent) => {
// 更新 showRowSelection
showRowSelectionUpdate(e.target.checked);
// 更新 showRowSelection 缓存
tableSettingStore.setShowRowSelection(e.target.checked);
};
// 更新列缓存
const columnOptionsSave = () => {
if (typeof route.name === 'string') {
// 按路由 name 作为缓存的key若一个路由内存在多个表格需自行调整缓存key来源
tableSettingStore.setColumns(route.name, columnOptions.value);
}
};
// 重置
const onReset = () => {
// 重置默认值
isIndexColumnShow.value = defaultIsIndexColumnShow;
// 序号列更新
onIndexColumnShowChange({
target: { checked: defaultIsIndexColumnShow },
} as CheckboxChangeEvent);
// 重置默认值
isRowSelectionShow.value = defaultIsRowSelectionShow;
// 选择列更新
onRowSelectionShowChange({
target: { checked: defaultIsRowSelectionShow },
} as CheckboxChangeEvent);
// 重置默认值
columnOptions.value = cloneDeep(defaultColumnOptions);
// 重置排序
sortableOrder = defaultSortableOrder;
// 排序
sortable?.sort(defaultSortableOrder);
// 更新表单状态
formUpdate();
};
// 设置列的 fixed
const onColumnFixedChange = (opt: ColumnOptionsType, type: 'left' | 'right') => {
if (type === 'left') {
if (!opt.fixed || opt.fixed === 'right') {
opt.fixed = 'left';
} else {
opt.fixed = undefined;
}
} else if (type === 'right') {
if (!opt.fixed || opt.fixed === 'left') {
opt.fixed = 'right';
} else {
opt.fixed = undefined;
}
}
// 列表列更新
tableColumnsUpdate();
// 更新列缓存
columnOptionsSave();
};
// 沿用逻辑
const sortableFix = async () => {
// Sortablejs存在bug不知道在哪个步骤中会向el append了一个childNode因此这里先清空childNode
// 有可能复现上述问题的操作:拖拽一个元素,快速的上下移动,最后放到最后的位置中松手
plainOptions.value = [];
const columnListEl = unref(columnListRef);
if (columnListEl && (columnListEl as any).$el) {
const el = (columnListEl as any).$el as Element;
if (columnOptionsRef.value) {
const el = (columnOptionsRef.value as InstanceType<typeof Checkbox.Group>).$el;
Array.from(el.children).forEach((item) => el.removeChild(item));
}
await nextTick();
const columns = isReset ? cloneDeep(cachePlainOptions.value) : getColumns();
};
const checkList = table
.getColumns({ ignoreAction: true, ignoreIndex: true })
.map((item) => {
if (item.defaultHidden) {
return '';
// 列是否显示逻辑
const columnIfShow = (column?: Partial<Omit<BasicColumn, 'children'>>) => {
if (column) {
if ('ifShow' in column) {
if (typeof column.ifShow === 'boolean') {
return column.ifShow;
} else if (column.ifShow) {
return column.ifShow(column);
}
return item.dataIndex || item.title;
})
.filter(Boolean) as string[];
plainOptions.value = columns;
plainSortOptions.value = columns;
// 更新缓存配置
table.setCacheColumns?.(columns);
!isReset && (cachePlainOptions.value = cloneDeep(columns));
state.defaultCheckList = checkList;
state.checkedList = checkList;
// 是否列展示全选
state.checkAll = checkList.length === columns.length;
inited = false;
handleVisibleChange();
}
// checkAll change
function onCheckAllChange(e: CheckboxChangeEvent) {
const checkList = plainSortOptions.value.map((item) => item.value);
plainSortOptions.value.forEach(
(item) => ((item as BasicColumn).defaultHidden = !e.target.checked),
);
if (e.target.checked) {
state.checkedList = checkList;
setColumns(checkList);
} else {
state.checkedList = [];
setColumns([]);
}
return true;
}
}
const indeterminate = computed(() => {
const len = plainOptions.value.length;
let checkedLen = state.checkedList.length;
// unref(checkIndex) && checkedLen--;
return checkedLen > 0 && checkedLen < len;
});
// Trigger when check/uncheck a column
function onChange(checkedList: CheckboxValueType[]) {
const len = plainSortOptions.value.length;
state.checkAll = checkedList.length === len;
const sortList = unref(plainSortOptions).map((item) => item.value);
checkedList.sort((prev, next) => {
return sortList.indexOf(String(prev)) - sortList.indexOf(String(next));
});
unref(plainSortOptions).forEach((item) => {
(item as BasicColumn).defaultHidden = !checkedList.includes(item.value);
});
setColumns(checkedList as string[]);
}
return false;
};
// sortable 实例
let sortable: Sortable;
// 排序
let sortableOrder: string[] = [];
// reset columns
function reset() {
setColumns(cachePlainOptions.value);
init(true);
checkIndex.value = !!cacheTableProps.showIndexColumn;
checkSelect.value = !!cacheTableProps.rowSelection;
table.setProps({
showIndexColumn: checkIndex.value,
rowSelection: checkSelect.value ? defaultRowSelection : undefined,
});
sortable.sort(sortableOrder);
}
// Open the pop-up window for drag and drop initialization
function handleVisibleChange() {
if (inited) return;
nextTick(() => {
const columnListEl = unref(columnListRef);
if (!columnListEl) return;
const el = (columnListEl as any).$el;
if (!el) return;
// Drag and drop sort
// 获取数据列
const getTableColumns = () => {
return table
.getColumns({ ignoreIndex: true, ignoreAction: true })
.filter((col) => columnIfShow(col));
};
// 设置列表列
const tableColumnsSet = (columns: BasicColumn[]) => {
isInnerChange = true;
table?.setColumns(columns);
// 沿用逻辑
const columnChangeParams: ColumnChangeParam[] = columns.map((col) => ({
dataIndex: col.dataIndex ? col.dataIndex.toString() : '',
fixed: col.fixed,
visible: !col.defaultHidden,
}));
emit('columns-change', columnChangeParams);
};
// 列表列更新
const tableColumnsUpdate = () => {
// 考虑了所有列
const columns = cloneDeep(table.getColumns());
// 从左 fixed 最一列开始排序
let count = columns.filter((o) => o.fixed === 'left' || o.fixed === true).length;
// 按 columnOptions 的排序 调整 table.getColumns() 的顺序和值
for (const opt of columnOptions.value) {
const colIdx = columns.findIndex((o) => o.dataIndex === opt.value);
//
if (colIdx > -1) {
const target = columns[colIdx];
target.defaultHidden = opt.column?.defaultHidden;
target.fixed = opt.fixed;
columns.splice(colIdx, 1);
columns.splice(count++, 0, target); // 递增插入
}
}
// 设置列表列
tableColumnsSet(columns);
};
// 打开浮窗
const onOpenChange = async () => {
await nextTick();
if (columnOptionsRef.value) {
// 注册排序实例
const el = (columnOptionsRef.value as InstanceType<typeof Checkbox.Group>).$el;
sortable = Sortablejs.create(unref(el), {
animation: 500,
delay: 400,
delayOnTouchOnly: true,
handle: '.table-column-drag-icon ',
dataIdAttr: 'data-no',
onEnd: (evt) => {
const { oldIndex, newIndex } = evt;
if (isNil(oldIndex) || isNil(newIndex) || oldIndex === newIndex) {
return;
}
// Sort column
const columns = cloneDeep(plainSortOptions.value);
const options = cloneDeep(columnOptions.value);
// 排序
if (oldIndex > newIndex) {
columns.splice(newIndex, 0, columns[oldIndex]);
columns.splice(oldIndex + 1, 1);
options.splice(newIndex, 0, options[oldIndex]);
options.splice(oldIndex + 1, 1);
} else {
columns.splice(newIndex + 1, 0, columns[oldIndex]);
columns.splice(oldIndex, 1);
options.splice(newIndex + 1, 0, options[oldIndex]);
options.splice(oldIndex, 1);
}
plainSortOptions.value = columns;
setColumns(columns.filter((item) => state.checkedList.includes(item.value)));
// 更新 列可选项
columnOptions.value = options;
// 列表列更新
tableColumnsUpdate();
// 更新列缓存
columnOptionsSave();
},
});
// 记录原始order 序列
sortableOrder = sortable.toArray();
inited = true;
});
}
// Control whether the serial number column is displayed
function handleIndexCheckChange(e: CheckboxChangeEvent) {
isSetPropsFromThis = true;
isSetColumnsFromThis = true;
table.setProps({
showIndexColumn: e.target.checked,
});
}
// Control whether the check box is displayed
function handleSelectCheckChange(e: CheckboxChangeEvent) {
isSetPropsFromThis = true;
isSetColumnsFromThis = true;
table.setProps({
rowSelection: e.target.checked ? defaultRowSelection : undefined,
});
}
function handleColumnFixed(item: BasicColumn, fixed?: 'left' | 'right') {
if (!state.checkedList.includes(item.dataIndex as string)) return;
const columns = getColumns().filter((c: BasicColumn) =>
state.checkedList.includes(c.dataIndex as string),
) as BasicColumn[];
const isFixed = item.fixed === fixed ? false : fixed;
const index = columns.findIndex((col) => col.dataIndex === item.dataIndex);
if (index !== -1) {
columns[index].fixed = isFixed;
// 从缓存恢复
sortable.sort(sortableOrder);
}
item.fixed = isFixed;
};
if (isFixed && !item.width) {
item.width = 100;
// remove消失的列、push新出现的列
const diff = () => {
if (typeof route.name === 'string') {
let cache = tableSettingStore.getColumns(route.name);
if (cache) {
// value、label是否一致
if (
JSON.stringify(columnOptions.value.map((o) => ({ value: o.value, label: o.label }))) !==
JSON.stringify(cache.map((o) => ({ value: o.value, label: o.label })))
) {
const map = columnOptions.value.reduce((map, item) => {
map[item.value] = item.label;
return map;
}, {});
if (Array.isArray(cache)) {
// remove消失的列
cache = cache.filter((o) => map[o.value]);
// 更新label
cache.forEach((o) => {
o.label = map[o.value];
});
const cacheKeys = cache.map((o) => o.value);
// push新出现的列
cache = cache.concat(columnOptions.value.filter((o) => !cacheKeys.includes(o.value)));
// 更新缓存
tableSettingStore.setColumns(route.name, cache);
}
}
}
}
updateSortOption(item);
table.setCacheColumnsByField?.(item.dataIndex as string, { fixed: isFixed });
setColumns(columns);
}
};
function setColumns(columns: BasicColumn[] | string[]) {
isSetPropsFromThis = true;
isSetColumnsFromThis = true;
table.setColumns(columns);
const data: ColumnChangeParam[] = unref(plainSortOptions).map((col) => {
const visible =
columns.findIndex(
(c: BasicColumn | string) =>
c === col.value || (typeof c !== 'string' && c.dataIndex === col.value),
) !== -1;
return { dataIndex: col.value, fixed: col.fixed, visible };
// 从缓存恢复
const restore = () => {
// 设置过才恢复
if (typeof tableSettingStore.getShowIndexColumn === 'boolean') {
isIndexColumnShow.value = tableSettingStore.getShowIndexColumn;
}
if (typeof tableSettingStore.getShowRowSelection === 'boolean') {
isRowSelectionShow.value = defaultIsRowSelectionShow && tableSettingStore.getShowRowSelection;
}
// 序号列更新
onIndexColumnShowChange({
target: { checked: isIndexColumnShow.value },
} as CheckboxChangeEvent);
// 选择列更新
onRowSelectionShowChange({
target: { checked: isRowSelectionShow.value },
} as CheckboxChangeEvent);
if (typeof route.name === 'string') {
const cache = tableSettingStore.getColumns(route.name);
// 设置过才恢复
if (Array.isArray(cache)) {
columnOptions.value = cache;
}
}
};
// 从 列可选项 更新 已选列
const columnCheckedOptionsUpdate = () => {
columnCheckedOptions.value = columnOptions.value
.filter((o) => !o.column?.defaultHidden)
.map((o) => o.value);
};
// 从 列可选项 更新 全选状态
const isColumnAllSelectedUpdate = () => {
isColumnAllSelected.value = columnOptions.value.length === columnCheckedOptions.value.length;
};
// 从 列可选项 更新 排序
const sortableOrderUpdateByOptions = (options: ColumnOptionsType[]) => {
sortableOrder = options.map((o) => o.value);
};
// 更新 showIndexColumn
const showIndexColumnUpdate = (showIndexColumn) => {
isInnerChange = true;
table.setProps({
showIndexColumn,
});
};
// 更新 rowSelection
const showRowSelectionUpdate = (showRowSelection) => {
isInnerChange = true;
table.setProps({
rowSelection: showRowSelection
? {
...defaultRowSelection,
fixed: true,
}
: undefined,
});
};
emit('columns-change', data);
}
// 更新表单状态
const formUpdate = () => {
// 从 列可选项 更新 已选列
columnCheckedOptionsUpdate();
function getPopupContainer() {
return isFunction(attrs.getPopupContainer) ? attrs.getPopupContainer() : getParentContainer();
}
// 从 列可选项 更新 全选状态
isColumnAllSelectedUpdate();
function updateSortOption(column: BasicColumn) {
plainSortOptions.value.forEach((item) => {
if (item.value === column.dataIndex) {
Object.assign(item, column);
// 从 列可选项 更新 排序
sortableOrderUpdateByOptions(columnOptions.value);
// 更新 showIndexColumn
showIndexColumnUpdate(isIndexColumnShow.value);
// 更新 showRowSelection
showRowSelectionUpdate(isRowSelectionShow.value);
// 列表列更新
tableColumnsUpdate();
};
// 默认值
let defaultIsIndexColumnShow: boolean = false;
let defaultIsRowSelectionShow: boolean = false;
let defaultRowSelection: TableRowSelection<Recordable<any>>;
let defaultColumnOptions: ColumnOptionsType[] = [];
let defaultSortableOrder: string[] = [];
const init = async () => {
if (!isRestored) {
await sortableFix();
// 获取数据列
const columns = getTableColumns();
// 沿用逻辑
table.setCacheColumns?.(columns);
// 生成 默认值
const options: ColumnOptionsType[] = [];
for (const col of columns) {
// 只缓存 string 类型的列
options.push({
label:
typeof col.title === 'string'
? col.title
: col.customTitle === 'string'
? col.customTitle
: '',
value:
typeof col.dataIndex === 'string'
? col.dataIndex
: col.title === 'string'
? col.title
: '',
column: {
defaultHidden: col.defaultHidden,
},
fixed: col.fixed,
});
}
// 默认值 缓存,浮窗出现的时候使用
defaultSortableOrder = options.map((o) => o.value);
// 默认值 缓存
defaultIsIndexColumnShow = table.getBindValues.value.showIndexColumn || false;
defaultRowSelection = table.getRowSelection();
defaultIsRowSelectionShow = !!defaultRowSelection; // 设置了 rowSelection 才出现
defaultColumnOptions = options;
// 默认值 赋值
isIndexColumnShow.value = defaultIsIndexColumnShow;
isRowSelectionShow.value = defaultIsRowSelectionShow;
columnOptions.value = cloneDeep(options);
// remove消失的列、push新出现的列
diff();
// 从缓存恢复
restore();
// 更新表单状态
formUpdate();
isRestored = true;
}
};
// 初始化
init();
// 外部列改变
const getColumns = computed(() => {
return table?.getColumns();
});
const getValues = computed(() => {
return table?.getBindValues;
});
onMounted(() => {
watch([getColumns, getValues], () => {
if (!isInnerChange) {
isRestored = false;
console.log('onMounted isRestored');
init();
} else {
isInnerChange = false;
}
});
}
});
</script>
<style lang="less">
@prefix-cls: ~'@{namespace}-basic-column-setting';

View File

@@ -24,13 +24,17 @@
</template>
<script lang="ts" setup>
import type { SizeType } from '../../types/table';
import { ref } from 'vue';
import { ref, onMounted } from 'vue';
import { Tooltip, Dropdown, Menu, type MenuProps } from 'ant-design-vue';
import { ColumnHeightOutlined } from '@ant-design/icons-vue';
import { useI18n } from '@/hooks/web/useI18n';
import { useTableContext } from '../../hooks/useTableContext';
import { getPopupContainer } from '@/utils';
import { useTableSettingStore } from '@/store/modules/tableSetting';
const tableSettingStore = useTableSettingStore();
defineOptions({ name: 'SizeSetting' });
const table = useTableContext();
@@ -40,8 +44,18 @@
const handleTitleClick: MenuProps['onClick'] = ({ key }) => {
selectedKeysRef.value = [key as SizeType];
tableSettingStore.setTableSize(key as SizeType);
table.setProps({
size: key as SizeType,
});
};
onMounted(() => {
selectedKeysRef.value = [tableSettingStore.getTableSize];
table.setProps({
size: selectedKeysRef.value[0],
});
});
</script>

View File

@@ -11,6 +11,7 @@ import type { ColumnProps } from 'ant-design-vue/lib/table';
import { ComponentType } from './componentType';
import { VueNode } from '@/utils/propTypes';
import { RoleEnum } from '@/enums/roleEnum';
import { FixedType } from 'ant-design-vue/es/vc-table/interface';
export declare type SortOrder = 'ascend' | 'descend';
@@ -485,3 +486,14 @@ export type ColumnChangeParam = {
export interface InnerHandlers {
onColumnsChange: (data: ColumnChangeParam[]) => void;
}
export interface ColumnOptionsType {
value: string;
label: string;
//
column: {
defaultHidden?: boolean;
};
//
fixed?: FixedType;
}

View File

@@ -26,6 +26,9 @@ export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__';
// base global session key
export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY__';
// table 列设置
export const TABLE_SETTING_KEY = 'TABLE__SETTING__KEY__';
export enum CacheTypeEnum {
SESSION,
LOCAL,

View File

@@ -0,0 +1,99 @@
import { defineStore } from 'pinia';
import { TABLE_SETTING_KEY } from '@/enums/cacheEnum';
import { Persistent } from '@/utils/cache/persistent';
import type { TableSetting } from '#/store';
import type { SizeType, ColumnOptionsType } from '@/components/Table/src/types/table';
interface TableSettingState {
setting: Nullable<Partial<TableSetting>>;
}
export const useTableSettingStore = defineStore({
id: 'table-setting',
state: (): TableSettingState => ({
setting: Persistent.getLocal(TABLE_SETTING_KEY),
}),
getters: {
getTableSetting(state): Nullable<Partial<TableSetting>> {
return state.setting;
},
//
getTableSize(state) {
return state.setting?.size || 'middle';
},
//
getShowIndexColumn(state) {
return state.setting?.showIndexColumn;
},
//
getShowRowSelection(state) {
return state.setting?.showRowSelection;
},
//
getColumns(state) {
return (routerName: string) => {
return state.setting?.columns && state.setting?.columns[routerName]
? state.setting?.columns[routerName]
: null;
};
},
},
actions: {
setTableSetting(setting: Partial<TableSetting>) {
this.setting = Object.assign({}, this.setting, setting);
Persistent.setLocal(TABLE_SETTING_KEY, this.setting, true);
},
resetTableSetting() {
Persistent.removeLocal(TABLE_SETTING_KEY, true);
this.setting = null;
},
//
setTableSize(size: SizeType) {
this.setTableSetting(
Object.assign({}, this.setting, {
size,
}),
);
},
//
setShowIndexColumn(show: boolean) {
this.setTableSetting(
Object.assign({}, this.setting, {
showIndexColumn: show,
}),
);
},
//
setShowRowSelection(show: boolean) {
this.setTableSetting(
Object.assign({}, this.setting, {
showRowSelection: show,
}),
);
},
//
setColumns(routerName: string, columns: Array<ColumnOptionsType>) {
this.setTableSetting(
Object.assign({}, this.setting, {
columns: {
...this.setting?.columns,
[routerName]: columns,
},
}),
);
},
clearColumns(routerName: string) {
this.setTableSetting(
Object.assign({}, this.setting, {
columns: {
...this.setting?.columns,
[routerName]: undefined,
},
}),
);
},
},
});

View File

@@ -1,4 +1,4 @@
import type { LockInfo, UserInfo } from '#/store';
import type { LockInfo, UserInfo, TableSetting } from '#/store';
import type { ProjectConfig } from '#/config';
import type { RouteLocationNormalized } from 'vue-router';
@@ -13,6 +13,7 @@ import {
APP_LOCAL_CACHE_KEY,
APP_SESSION_CACHE_KEY,
MULTIPLE_TABS_KEY,
TABLE_SETTING_KEY,
} from '@/enums/cacheEnum';
import { DEFAULT_CACHE_TIME } from '@/settings/encryptionSetting';
import { toRaw } from 'vue';
@@ -25,6 +26,7 @@ interface BasicStore {
[LOCK_INFO_KEY]: LockInfo;
[PROJ_CFG_KEY]: ProjectConfig;
[MULTIPLE_TABS_KEY]: RouteLocationNormalized[];
[TABLE_SETTING_KEY]: Partial<TableSetting>;
}
type LocalStore = BasicStore;

7
types/store.d.ts vendored
View File

@@ -51,3 +51,10 @@ export interface BeforeMiniState {
menuMode?: MenuModeEnum;
menuType?: MenuTypeEnum;
}
export interface TableSetting {
size: Nullable<SizeType>;
showIndexColumn: Nullable<boolean>;
columns: Recordable<Nullable<Array<ColumnOptionsType>>>;
showRowSelection: Nullable<boolean>;
}