列设置添加缓存

调整监测点台账导出id重复问题
This commit is contained in:
guanj
2026-07-17 08:50:25 +08:00
parent dc3b3cfc74
commit 6c70a776a0
9 changed files with 173 additions and 133 deletions

View File

@@ -1,23 +1,41 @@
<script lang='ts'>
import { defineComponent, createVNode, reactive } from 'vue'
import { Column } from 'vxe-table'
import { uuid } from '@/utils/random'
export default defineComponent({
name: 'Column',
props: {
attr: {
type: Object,
required: true
}
},
setup(props, { slots }) {
const attr = reactive(props.attr)
attr['align'] = attr['align'] ? attr['align'] : 'center'
attr['column-key'] = attr['column-key'] ? attr['column-key'] : attr.prop || uuid()
return () => {
return createVNode(Column, attr, slots.default)
}
}
})
</script>
<script lang="ts">
import { defineComponent, createVNode, reactive } from 'vue'
import { Column } from 'vxe-table'
import { uuid } from '@/utils/random'
/** storage 开启时列必须有稳定 field序号/操作等无 field 列按 title 生成 */
function resolveColumnField(attr: Record<string, any>): string | undefined {
if (attr.field) return attr.field
if (attr.prop) return attr.prop
// checkbox / radio / expand / seq 等类型列由 vxe 内部处理,可不强制 field
if (attr.type && ['checkbox', 'radio', 'expand', 'html'].includes(attr.type)) {
return undefined
}
if (attr.title != null && attr.title !== '') {
return `__col_${attr.title}`
}
return `col_${uuid()}`
}
export default defineComponent({
name: 'Column',
props: {
attr: {
type: Object,
required: true
}
},
setup(props, { slots }) {
const attr = reactive({ ...props.attr })
attr['align'] = attr['align'] ? attr['align'] : 'center'
const field = resolveColumnField(attr)
if (field) {
attr.field = field
}
attr['column-key'] = attr['column-key'] ? attr['column-key'] : attr.field || attr.prop || uuid()
return () => {
return createVNode(Column, attr, slots.default)
}
}
})
</script>

View File

@@ -7,11 +7,11 @@ export const defaultAttribute: VxeTableProps = {
stripe: true,
size: 'small',
columnConfig: { resizable: true, useKey: true },
rowConfig: { isCurrent: true, isHover: true, keyField: 'id' },
rowConfig: { isCurrent: true, isHover: true, },
scrollX: { scrollToLeftOnChange: true },
scrollY: { enabled: false },
// 注意:全局不要默认开启 treeConfig会与 stripe 冲突;树表在页面自行配置
customConfig: { enabled: true, allowFixed: false, showFooter: false, immediate: true, mode: 'default' },
customConfig: { enabled: true, allowFixed: true, storage: true, showFooter: false, immediate: true ,mode:'default'},
showOverflow: 'tooltip',
showHeaderOverflow: false
}

View File

@@ -1,20 +1,23 @@
<template>
<div :style="{ height: typeof props.height === 'string' ? props.height : tableStore.table.height }">
<div v-if="showCustomColumn && !tableStore?.table?.customColumnInHeader" class="table-custom-toolbar">
<el-button icon="el-icon-Setting" @mousedown="onCustomColumnMousedown" @click="openCustomColumn">列设置</el-button>
<el-button icon="el-icon-Setting" @mousedown="onCustomColumnMousedown" @click="openCustomColumn">
列设置
</el-button>
</div>
<vxe-table
ref="tableRef"
height="auto"
:key="key"
:id="getTableId()"
:data="tableStore.table.data"
v-loading="tableStore.table.loading"
v-bind="tableBindProps"
v-bind="tableBindProps"
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
@cell-click="onCellClick"
>
<!-- @sort-change="handleSortChange" -->
<!-- @sort-change="handleSortChange" -->
<!-- Column 组件内部是 el-table-column -->
<template v-if="isGroup">
<GroupColumn :column="tableStore.table.column" />
@@ -163,6 +166,9 @@ const openCustomColumn = () => {
const getRef = () => {
return tableRef.value
}
const getTableId = () => {
return tableStore.table.filename || document.querySelectorAll('.ba-nav-tab.active')[0].textContent || ''
}
// 排序
const handleSortChange = ({ column, order }: { column: TableColumn; order: 'asc' | 'desc' | null }) => {
// console.log('排序列:', column?.property);

View File

@@ -43,6 +43,7 @@ import { useConfig } from '@/stores/config'
import { useAdminInfo } from '@/stores/adminInfo'
import { useNavTabs } from '@/stores/navTabs'
import { logout } from '@/api/user-boot/user'
import { Local } from '@/utils/storage'
import Config from './config.vue'
import PopupPwd from './popup/password.vue'
import AdminInfo from './popup/adminInfo.vue'
@@ -114,8 +115,8 @@ const handleLogout = async () => {
// 清理本地数据
const clearLocalData = () => {
// 清空 localStorage
window.localStorage.clear()
// 清空 localStorage(保留 VXE 自定义列、DevTools 配置)
Local.clear()
// 清空用户状态
adminInfo.reset()

View File

@@ -30,6 +30,7 @@ import { validatePwd } from '@/utils/common'
import { useAdminInfo } from '@/stores/adminInfo'
import router from '@/router'
import { useNavTabs } from '@/stores/navTabs'
import { Local } from '@/utils/storage'
const navTabs = useNavTabs()
const adminInfo = useAdminInfo()
const dialogVisible = ref(false)
@@ -103,7 +104,7 @@ const submit = () => {
dialogVisible.value = false
setTimeout(() => {
navTabs.closeTabs()
window.localStorage.clear()
Local.clear()
adminInfo.reset()
router.push({ name: 'login' })
}, 0)

View File

@@ -1,54 +1,54 @@
.block-loading {
width: 100%;
height: 100%;
position: fixed;
z-index: 9990;
background-color: var(--ba-bg-color);
}
.block-loading .block-loading-box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.block-loading .block-loading-box-warp {
width: 80px;
height: 80px;
}
.block-loading .block-loading-box-warp .block-loading-box-item {
width: 33.333333%;
height: 33.333333%;
background: #409eff;
float: left;
animation: block-loading-animation 1.2s infinite ease;
border-radius: 1px;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(7) {
animation-delay: 0s;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(4),
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(8) {
animation-delay: 0.1s;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(1),
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(5),
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(9) {
animation-delay: 0.2s;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(2),
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(6) {
animation-delay: 0.3s;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes block-loading-animation {
0%,
70%,
100% {
transform: scale3D(1, 1, 1);
}
35% {
transform: scale3D(0, 0, 1);
}
}
.block-loading {
width: 100%;
height: 100%;
position: fixed;
z-index: 9990;
background-color: var(--ba-bg-color);
}
.block-loading .block-loading-box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.block-loading .block-loading-box-warp {
width: 80px;
height: 80px;
}
.block-loading .block-loading-box-warp .block-loading-box-item {
width: 33.333333%;
height: 33.333333%;
background: #409eff;
float: left;
animation: block-loading-animation 1.2s infinite ease;
border-radius: 1px;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(7) {
animation-delay: 0s;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(4),
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(8) {
animation-delay: 0.1s;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(1),
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(5),
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(9) {
animation-delay: 0.2s;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(2),
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(6) {
animation-delay: 0.3s;
}
.block-loading .block-loading-box-warp .block-loading-box-item:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes block-loading-animation {
0%,
70%,
100% {
transform: scale3D(1, 1, 1);
}
35% {
transform: scale3D(0, 0, 1);
}
}

View File

@@ -1,45 +1,59 @@
/**
* window.localStorage
* @method set 设置
* @method get 获取
* @method remove 移除
* @method clear 移除全部
*/
export const Local = {
set(key: string, val: any) {
window.localStorage.setItem(key, JSON.stringify(val))
},
get(key: string) {
const json: any = window.localStorage.getItem(key)
return JSON.parse(json)
},
remove(key: string) {
window.localStorage.removeItem(key)
},
clear() {
window.localStorage.clear()
},
}
/**
* window.sessionStorage
* @method set 设置会话缓存
* @method get 获取会话缓存
* @method remove 移除会话缓存
* @method clear 移除全部会话缓存
*/
export const Session = {
set(key: string, val: any) {
window.sessionStorage.setItem(key, JSON.stringify(val))
},
get(key: string) {
const json: any = window.sessionStorage.getItem(key)
return JSON.parse(json)
},
remove(key: string) {
window.sessionStorage.removeItem(key)
},
clear() {
window.sessionStorage.clear()
},
}
/**
* window.localStorage
* @method set 设置
* @method get 获取
* @method remove 移除
* @method clear 移除全部
*/
export const Local = {
set(key: string, val: any) {
window.localStorage.setItem(key, JSON.stringify(val))
},
get(key: string) {
const json: any = window.localStorage.getItem(key)
return JSON.parse(json)
},
remove(key: string) {
window.localStorage.removeItem(key)
},
clear() {
// 退出登录时保留表格自定义列、Vue DevTools 等配置
const preserveKeys = [
'VXE_CUSTOM_STORE',
'__VUE_DEVTOOLS_NEXT_PLUGIN_SETTINGS__dev.esm.pinia__',
]
const preserved: Record<string, string | null> = {}
preserveKeys.forEach(key => {
preserved[key] = window.localStorage.getItem(key)
})
window.localStorage.clear()
preserveKeys.forEach(key => {
if (preserved[key] !== null) {
window.localStorage.setItem(key, preserved[key] as string)
}
})
},
}
/**
* window.sessionStorage
* @method set 设置会话缓存
* @method get 获取会话缓存
* @method remove 移除会话缓存
* @method clear 移除全部会话缓存
*/
export const Session = {
set(key: string, val: any) {
window.sessionStorage.setItem(key, JSON.stringify(val))
},
get(key: string) {
const json: any = window.sessionStorage.getItem(key)
return JSON.parse(json)
},
remove(key: string) {
window.sessionStorage.removeItem(key)
},
clear() {
window.sessionStorage.clear()
},
}

View File

@@ -109,7 +109,7 @@ const tableStore = new TableStore({
publicHeight: 65,
isWebPaging: true,
method: 'POST',
filename: '监测点台账',
filename: '监测点台账 ',
column: [
{
title: '序号',
@@ -155,7 +155,7 @@ const tableStore = new TableStore({
{ field: 'powerFlag', title: '用户性质', width: '120px' },
/* { field: 'comFlag', title: '通讯状态 ', minWidth: 120 },*/
{ field: 'id', title: '监测点序号', minWidth: 90 },
{ field: 'runNo', title: '监测点序号', minWidth: 90 },
{
field: 'comFlag',
title: '通讯状态',

View File

@@ -53,7 +53,7 @@
maxlength="32"
show-word-limit
clearable
style="minWidth: 280px;"
style="min-Width: 280px;"
/>
</el-form-item>
</template>