feat: 表格相关缓存存入前端indexDB
This commit is contained in:
parent
6f26154738
commit
8038acdd22
|
@ -50,6 +50,7 @@
|
|||
"hotbox-minder": "1.0.15",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"jsonpath-picker-vanilla": "^1.2.4",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"monaco-editor": "^0.39.0",
|
||||
|
|
|
@ -53,7 +53,13 @@
|
|||
:tooltip="item.tooltip"
|
||||
>
|
||||
<template #title>
|
||||
<div v-if="props.showSetting && idx === lastColumnIndex" class="flex flex-row flex-nowrap items-center">
|
||||
<div
|
||||
v-if="
|
||||
props.showSetting &&
|
||||
(item.slotName === SpecialColumnEnum.OPERATION || item.slotName === SpecialColumnEnum.ACTION)
|
||||
"
|
||||
class="flex flex-row flex-nowrap items-center"
|
||||
>
|
||||
<slot :name="item.titleSlotName">
|
||||
<div class="text-[var(--color-text-3)]">{{ t(item.title as string) }}</div>
|
||||
</slot>
|
||||
|
@ -240,8 +246,6 @@
|
|||
(e: 'clearSelector'): void;
|
||||
}>();
|
||||
const attrs = useAttrs();
|
||||
const lastColumnIndex = computed(() => currentColumns.value.length - 1);
|
||||
|
||||
// 全选按钮-总条数
|
||||
const selectTotal = computed(() => {
|
||||
const { selectorStatus } = props;
|
||||
|
@ -300,14 +304,19 @@
|
|||
return undefined;
|
||||
});
|
||||
|
||||
const initColumn = (arr?: MsTableColumn) => {
|
||||
let tmpArr: MsTableColumn = [];
|
||||
if (props.showSetting) {
|
||||
tmpArr = tableStore.getShowInTableColumns(attrs.tableKey as string) || [];
|
||||
} else {
|
||||
tmpArr = props.columns;
|
||||
const initColumn = async (arr?: MsTableColumn) => {
|
||||
try {
|
||||
let tmpArr: MsTableColumn = [];
|
||||
if (props.showSetting) {
|
||||
tmpArr = await tableStore.getShowInTableColumns(attrs.tableKey as string);
|
||||
} else {
|
||||
tmpArr = props.columns;
|
||||
}
|
||||
currentColumns.value = arr || tmpArr;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('InitColumn failed', error);
|
||||
}
|
||||
currentColumns.value = arr || tmpArr;
|
||||
};
|
||||
|
||||
// 全选change事件
|
||||
|
@ -415,8 +424,8 @@
|
|||
}
|
||||
};
|
||||
|
||||
const handleColumnSelectorClose = () => {
|
||||
initColumn();
|
||||
const handleColumnSelectorClose = async () => {
|
||||
await initColumn();
|
||||
};
|
||||
|
||||
function getRowClass(record: TableData, rowIndex: number) {
|
||||
|
@ -429,8 +438,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initColumn();
|
||||
onMounted(async () => {
|
||||
await initColumn();
|
||||
batchLeft.value = getBatchLeft();
|
||||
});
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<template v-if="showJumpMethod">
|
||||
<div class="mb-2 flex items-center">
|
||||
<span class="text-[var(--color-text-4)]">{{ t('msTable.columnSetting.mode') }}</span>
|
||||
<a-tooltip :content="t('msTable.columnSetting.tooltipContent')">
|
||||
<a-tooltip>
|
||||
<template #content>
|
||||
<span>{{ t('msTable.columnSetting.tooltipContentDrawer') }}</span
|
||||
><br />
|
||||
|
@ -39,14 +39,14 @@
|
|||
</a-radio>
|
||||
</a-radio-group>
|
||||
</template>
|
||||
<tmplate v-if="props.showPagination">
|
||||
<template v-if="props.showPagination">
|
||||
<div class="text-[var(--color-text-4)]">{{ t('msTable.columnSetting.pageSize') }} </div>
|
||||
<PageSizeSelector
|
||||
v-model:model-value="pageSize"
|
||||
class="mt-2"
|
||||
@page-size-change="(v: number) => emit('pageSizeChange',v)"
|
||||
/>
|
||||
</tmplate>
|
||||
</template>
|
||||
<a-divider />
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<div class="text-[var(--color-text-4)]">{{ t('msTable.columnSetting.header') }}</div>
|
||||
|
@ -91,7 +91,7 @@
|
|||
import PageSizeSelector from './comp/pageSizeSelector.vue';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useAppStore, useTableStore } from '@/store';
|
||||
import { useTableStore } from '@/store';
|
||||
import { TableOpenDetailMode } from '@/store/modules/ms-table/types';
|
||||
|
||||
import { MsTableColumn } from './type';
|
||||
|
@ -100,8 +100,7 @@
|
|||
const tableStore = useTableStore();
|
||||
const { t } = useI18n();
|
||||
const currentMode = ref('');
|
||||
const appStore = useAppStore();
|
||||
const pageSize = ref(appStore.pageSize);
|
||||
const pageSize = ref();
|
||||
// 不能拖拽的列
|
||||
const nonSortColumn = ref<MsTableColumn>([]);
|
||||
// 可以拖拽的列
|
||||
|
@ -126,8 +125,8 @@
|
|||
visible.value = true;
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
tableStore.setColumns(
|
||||
const handleCancel = async () => {
|
||||
await tableStore.setColumns(
|
||||
props.tableKey,
|
||||
[...nonSortColumn.value, ...couldSortColumn.value],
|
||||
currentMode.value as TableOpenDetailMode
|
||||
|
@ -137,9 +136,11 @@
|
|||
};
|
||||
|
||||
const loadColumn = (key: string) => {
|
||||
const { nonSort, couldSort } = tableStore.getColumns(key);
|
||||
nonSortColumn.value = nonSort;
|
||||
couldSortColumn.value = couldSort;
|
||||
tableStore.getColumns(key).then((res) => {
|
||||
const { nonSort, couldSort } = res;
|
||||
nonSortColumn.value = nonSort;
|
||||
couldSortColumn.value = couldSort;
|
||||
});
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
|
@ -153,7 +154,12 @@
|
|||
|
||||
onBeforeMount(() => {
|
||||
if (props.tableKey) {
|
||||
currentMode.value = tableStore.getMode(props.tableKey);
|
||||
tableStore.getMode(props.tableKey).then((res) => {
|
||||
currentMode.value = res;
|
||||
});
|
||||
tableStore.getPageSize(props.tableKey).then((res) => {
|
||||
pageSize.value = res;
|
||||
});
|
||||
loadColumn(props.tableKey);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -111,8 +111,11 @@ export default function useTableProps<T>(
|
|||
|
||||
// 如果表格设置了tableKey,设置缓存的分页大小
|
||||
if (propsRes.value.msPagination && typeof propsRes.value.msPagination === 'object' && propsRes.value.tableKey) {
|
||||
const pageSize = tableStore.getPageSize(propsRes.value.tableKey);
|
||||
propsRes.value.msPagination.pageSize = pageSize;
|
||||
tableStore.getPageSize(propsRes.value.tableKey).then((res) => {
|
||||
if (propsRes.value.msPagination && res) {
|
||||
propsRes.value.msPagination.pageSize = res;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,12 +165,17 @@ export default function useTableProps<T>(
|
|||
if (propsRes.value.showPagination) {
|
||||
const { current, pageSize } = propsRes.value.msPagination as Pagination;
|
||||
const { rowKey, selectorStatus, excludeKeys } = propsRes.value;
|
||||
let currentPageSize = pageSize;
|
||||
if (propsRes.value.tableKey) {
|
||||
// 如果表格设置了tableKey,缓存分页大小
|
||||
currentPageSize = await tableStore.getPageSize(propsRes.value.tableKey);
|
||||
}
|
||||
try {
|
||||
if (loadListFunc) {
|
||||
setLoading(true);
|
||||
const data = await loadListFunc({
|
||||
current,
|
||||
pageSize,
|
||||
pageSize: currentPageSize,
|
||||
sort: sortItem.value,
|
||||
filter: filterItem.value,
|
||||
keyword: keyword.value,
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
import { filter, orderBy } from 'lodash-es';
|
||||
|
||||
import { MsTableColumn, MsTableColumnData } from '@/components/pure/ms-table/type';
|
||||
|
||||
import { useAppStore } from '@/store';
|
||||
import { PageSizeMap, SelectorColumnMap, TableOpenDetailMode } from '@/store/modules/ms-table/types';
|
||||
|
||||
import { SpecialColumnEnum } from '@/enums/tableEnum';
|
||||
|
||||
import localforage from 'localforage';
|
||||
|
||||
export default function useTableStore() {
|
||||
const state = reactive({
|
||||
baseSortIndex: 10,
|
||||
operationBaseIndex: 100,
|
||||
});
|
||||
|
||||
const getSelectorColumnMap = async () => {
|
||||
try {
|
||||
const selectorColumnMap = await localforage.getItem<SelectorColumnMap>('selectorColumnMap');
|
||||
if (!selectorColumnMap) {
|
||||
return {};
|
||||
}
|
||||
return selectorColumnMap;
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e);
|
||||
return {};
|
||||
}
|
||||
};
|
||||
const getPageSizeMap = async () => {
|
||||
try {
|
||||
const pageSizeMap = await localforage.getItem<PageSizeMap>('pageSizeMap');
|
||||
if (!pageSizeMap) {
|
||||
return {};
|
||||
}
|
||||
return pageSizeMap;
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e);
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
async function initColumn(tableKey: string, column: MsTableColumn, mode: TableOpenDetailMode) {
|
||||
try {
|
||||
const selectorColumnMap = await getSelectorColumnMap();
|
||||
if (!selectorColumnMap[tableKey]) {
|
||||
column.forEach((item, idx) => {
|
||||
if (item.sortIndex === undefined) {
|
||||
// 如果没有设置sortIndex,则默认按照顺序排序
|
||||
item.sortIndex = state.baseSortIndex + idx;
|
||||
}
|
||||
if (item.showDrag === undefined) {
|
||||
// 默认不可以拖拽
|
||||
item.showDrag = false;
|
||||
}
|
||||
if (item.showInTable === undefined) {
|
||||
// 默认在表格中展示
|
||||
item.showInTable = true;
|
||||
}
|
||||
if (item.dataIndex === SpecialColumnEnum.ID) {
|
||||
// dataIndex 为 id 的列默认不排序,且展示在列的最前面
|
||||
item.showDrag = false;
|
||||
item.sortIndex = 0;
|
||||
}
|
||||
if (item.dataIndex === SpecialColumnEnum.NAME) {
|
||||
// dataIndex 为 name 的列默认不排序,且展示在列的第二位
|
||||
item.showDrag = false;
|
||||
item.sortIndex = 1;
|
||||
}
|
||||
if (item.dataIndex === SpecialColumnEnum.OPERATION || item.dataIndex === SpecialColumnEnum.ACTION) {
|
||||
// dataIndex 为 operation 或 action 的列默认不排序,且展示在列的最后面
|
||||
item.showDrag = false;
|
||||
item.sortIndex = state.operationBaseIndex;
|
||||
}
|
||||
});
|
||||
selectorColumnMap[tableKey] = { mode, column };
|
||||
await localforage.setItem('selectorColumnMap', selectorColumnMap);
|
||||
}
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
async function setMode(key: string, mode: TableOpenDetailMode) {
|
||||
try {
|
||||
const selectorColumnMap = await getSelectorColumnMap();
|
||||
if (selectorColumnMap[key]) {
|
||||
const item = selectorColumnMap[key];
|
||||
if (item) {
|
||||
item.mode = mode;
|
||||
}
|
||||
await localforage.setItem('selectorColumnMap', selectorColumnMap);
|
||||
}
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
async function setColumns(key: string, columns: MsTableColumn, mode: TableOpenDetailMode) {
|
||||
try {
|
||||
columns.forEach((item, idx) => {
|
||||
if (item.showDrag) {
|
||||
item.sortIndex = state.baseSortIndex + idx;
|
||||
}
|
||||
});
|
||||
const selectorColumnMap = await getSelectorColumnMap();
|
||||
if (!selectorColumnMap) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectorColumnMap[key] = { mode, column: JSON.parse(JSON.stringify(columns)) };
|
||||
await localforage.setItem('selectorColumnMap', selectorColumnMap);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('tableStore.setColumns', e);
|
||||
}
|
||||
}
|
||||
async function setPageSize(key: string, pageSize: number) {
|
||||
const pageSizeMap = await getPageSizeMap();
|
||||
pageSizeMap[key] = pageSize;
|
||||
await localforage.setItem('pageSizeMap', pageSizeMap);
|
||||
}
|
||||
|
||||
async function getMode(key: string) {
|
||||
const selectorColumnMap = await getSelectorColumnMap();
|
||||
if (selectorColumnMap[key]) {
|
||||
return selectorColumnMap[key].mode;
|
||||
}
|
||||
return 'drawer';
|
||||
}
|
||||
async function getColumns(key: string) {
|
||||
const selectorColumnMap = await getSelectorColumnMap();
|
||||
if (selectorColumnMap[key]) {
|
||||
const tmpArr = selectorColumnMap[key].column;
|
||||
const nonSortableColumns = tmpArr.filter((item: MsTableColumnData) => !item.showDrag);
|
||||
const couldSortableColumns = tmpArr.filter((item: MsTableColumnData) => !!item.showDrag);
|
||||
return { nonSort: nonSortableColumns, couldSort: couldSortableColumns };
|
||||
}
|
||||
return { nonSort: [], couldSort: [] };
|
||||
}
|
||||
async function getShowInTableColumns(key: string) {
|
||||
const selectorColumnMap = await getSelectorColumnMap();
|
||||
if (selectorColumnMap[key]) {
|
||||
const tmpArr: MsTableColumn = selectorColumnMap[key].column;
|
||||
return orderBy(
|
||||
filter(tmpArr, (i) => i.showInTable),
|
||||
['sortIndex'],
|
||||
['asc']
|
||||
) as MsTableColumn;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
async function getPageSize(key: string) {
|
||||
const pageSizeMap = await getPageSizeMap();
|
||||
if (pageSizeMap[key]) {
|
||||
return pageSizeMap[key];
|
||||
}
|
||||
return useAppStore().pageSize;
|
||||
}
|
||||
|
||||
return {
|
||||
initColumn,
|
||||
setMode,
|
||||
setColumns,
|
||||
setPageSize,
|
||||
getMode,
|
||||
getColumns,
|
||||
getShowInTableColumns,
|
||||
getPageSize,
|
||||
};
|
||||
}
|
|
@ -15,6 +15,7 @@ import router from './router';
|
|||
import store from './store';
|
||||
import ArcoVueIcon from '@arco-design/web-vue/es/icon';
|
||||
import '@/assets/style/global.less';
|
||||
import localforage from 'localforage';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = createApp(App);
|
||||
|
@ -28,6 +29,14 @@ async function bootstrap() {
|
|||
app.component('SvgIcon', SvgIcon);
|
||||
app.component('MsIcon', MsIcon);
|
||||
|
||||
// 初始化本地存储
|
||||
localforage.config({
|
||||
driver: localforage.INDEXEDDB, // 选择后端存储,这里使用 IndexedDB
|
||||
name: 'MeterSphere', // 数据库名称
|
||||
version: 1.0, // 数据库版本
|
||||
storeName: 'msTable', // 存储空间名称
|
||||
});
|
||||
|
||||
app.use(directive);
|
||||
|
||||
app.mount('#app');
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { createPinia } from 'pinia';
|
||||
|
||||
import useTableStore from '@/hooks/useTableStore';
|
||||
|
||||
import useAppStore from './modules/app';
|
||||
import useVisitStore from './modules/app/visit';
|
||||
import useTableStore from './modules/ms-table';
|
||||
import useUserStore from './modules/user';
|
||||
import { debouncePlugin } from './plugins';
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
|
||||
|
|
|
@ -10,9 +10,6 @@ import { MsTableState, TableOpenDetailMode } from './types';
|
|||
|
||||
const msTableStore = defineStore('msTable', {
|
||||
// 开启数据持久化
|
||||
persist: {
|
||||
paths: ['selectorColumnMap', 'pageSizeMap'],
|
||||
},
|
||||
state: (): MsTableState => ({
|
||||
selectorColumnMap: {},
|
||||
baseSortIndex: 10,
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
|
||||
|
@ -232,7 +231,7 @@
|
|||
watch(
|
||||
() => props.data,
|
||||
(val) => {
|
||||
totalData.value = props.data;
|
||||
totalData.value = val;
|
||||
}
|
||||
);
|
||||
const tableRef = ref();
|
||||
|
|
Loading…
Reference in New Issue