Merge branch 'dev' of http://120.46.213.136:9528/isoftstone/lc_frontend into dev
This commit is contained in:
@@ -0,0 +1,179 @@
|
|||||||
|
<template>
|
||||||
|
<ElDrawer
|
||||||
|
v-model="drawerVisible"
|
||||||
|
title="列显隐"
|
||||||
|
direction="rtl"
|
||||||
|
size="560px"
|
||||||
|
:z-index="3000"
|
||||||
|
>
|
||||||
|
<div class="column-config-drawer">
|
||||||
|
<el-table
|
||||||
|
:data="columnConfigList"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
max-height="calc(100vh - 200px)"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-table-column prop="label" label="列名" width="200" fixed="left">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span>{{ row.label }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="隐藏" width="80" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-checkbox
|
||||||
|
v-model="row.hide"
|
||||||
|
@change="handleConfigChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="冻结" width="80" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-checkbox
|
||||||
|
:model-value="row.fixed === 'left'"
|
||||||
|
@change="(val) => { row.fixed = val ? 'left' : false; handleConfigChange() }"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="排序" width="80" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-checkbox
|
||||||
|
:model-value="row.sortable === 'custom'"
|
||||||
|
@change="(val) => { row.sortable = val ? 'custom' : false; handleConfigChange() }"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<!-- 导出 -->
|
||||||
|
<el-table-column label="导出" width="80" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-checkbox
|
||||||
|
:model-value="row.isExport === 'Y'"
|
||||||
|
@change="(val) => { row.isExport = val ? 'Y' : 'N'; handleConfigChange() }"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</ElDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { debounce } from 'lodash-es'
|
||||||
|
|
||||||
|
defineOptions({ name: 'ColumnConfigDialog' })
|
||||||
|
|
||||||
|
interface ColumnConfig {
|
||||||
|
prop: string
|
||||||
|
label: string
|
||||||
|
hide: boolean
|
||||||
|
fixed: string | boolean
|
||||||
|
sortable: string | boolean
|
||||||
|
showColumn: boolean
|
||||||
|
sortNum?: number
|
||||||
|
isExport?: string // 'Y' 表示导出,'N' 表示不导出
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
modelValue: boolean
|
||||||
|
columns: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: boolean]
|
||||||
|
'confirm': [config: Record<string, any>]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const drawerVisible = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (val) => emit('update:modelValue', val)
|
||||||
|
})
|
||||||
|
|
||||||
|
const columnConfigList = ref<ColumnConfig[]>([])
|
||||||
|
|
||||||
|
const initColumnConfig = () => {
|
||||||
|
if (!props.columns) return
|
||||||
|
|
||||||
|
columnConfigList.value = Object.keys(props.columns)
|
||||||
|
.map(key => {
|
||||||
|
const column = props.columns[key]
|
||||||
|
return {
|
||||||
|
prop: column.prop || key,
|
||||||
|
label: column.label || key,
|
||||||
|
hide: column.hide || false,
|
||||||
|
fixed: column.fixed || false,
|
||||||
|
sortable: column.sortable || false,
|
||||||
|
showColumn: column.showColumn !== false,
|
||||||
|
sortNum: column.sortNum,
|
||||||
|
// 默认全部勾选导出,如果已有配置则使用配置值
|
||||||
|
isExport: column.isExport !== undefined ? column.isExport : 'Y'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
// 优先按 sortNum 排序(从小到大)
|
||||||
|
if (a.sortNum !== undefined && b.sortNum !== undefined) {
|
||||||
|
return a.sortNum - b.sortNum
|
||||||
|
}
|
||||||
|
if (a.sortNum !== undefined) return -1
|
||||||
|
if (b.sortNum !== undefined) return 1
|
||||||
|
// 如果都没有 sortNum,则按 label 排序
|
||||||
|
const labelA = a.label || ''
|
||||||
|
const labelB = b.label || ''
|
||||||
|
return labelA.localeCompare(labelB, 'zh-CN')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防抖保存配置
|
||||||
|
const saveConfig = debounce(() => {
|
||||||
|
const config: Record<string, any> = {}
|
||||||
|
|
||||||
|
columnConfigList.value.forEach(item => {
|
||||||
|
config[item.prop] = {
|
||||||
|
hide: item.hide,
|
||||||
|
fixed: item.fixed,
|
||||||
|
sortable: item.sortable,
|
||||||
|
isExport: item.isExport || 'Y' // 默认导出
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
emit('confirm', config)
|
||||||
|
}, 300)
|
||||||
|
|
||||||
|
const handleConfigChange = () => {
|
||||||
|
// 配置变化时直接触发保存(防抖处理)
|
||||||
|
saveConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
initColumnConfig()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.columns,
|
||||||
|
() => {
|
||||||
|
if (props.modelValue) {
|
||||||
|
initColumnConfig()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.column-config-drawer {
|
||||||
|
:deep(.el-table) {
|
||||||
|
.el-table__header {
|
||||||
|
th {
|
||||||
|
background-color: var(--el-fill-color-light);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -116,7 +116,7 @@ const initColumn = (data, componentData, columnParams) => {
|
|||||||
const summaryBottom = {}
|
const summaryBottom = {}
|
||||||
const tableDic = {}
|
const tableDic = {}
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
const { dictEntity, webEntity, queryEntity, exportEntity, summaryEntity, fieldCode, fieldName, fieldType, fieldLen, fieldPointLen, fieldDefaultVal } = item
|
const { dictEntity, webEntity, queryEntity, exportEntity, summaryEntity, fieldCode, fieldName, fieldType, fieldLen, fieldPointLen, fieldDefaultVal, sortNum } = item
|
||||||
const { cellWidthType, cellWidth, controlsConfig, verifyConfig, isShowForm, isShowList, isDbSelect, isShowColumn, isShowSort, isRequired } = webEntity
|
const { cellWidthType, cellWidth, controlsConfig, verifyConfig, isShowForm, isShowList, isDbSelect, isShowColumn, isShowSort, isRequired } = webEntity
|
||||||
let controlType = webEntity.controlType || 'input'
|
let controlType = webEntity.controlType || 'input'
|
||||||
const { queryIsWeb, queryMode, queryConfig, queryDefaultVal } = queryEntity
|
const { queryIsWeb, queryMode, queryConfig, queryDefaultVal } = queryEntity
|
||||||
@@ -140,7 +140,8 @@ const initColumn = (data, componentData, columnParams) => {
|
|||||||
dataType: ['Integer', 'BigInt', 'BigDecimal'].includes(fieldType) || controlType == 'number' ? 'number' : 'string',
|
dataType: ['Integer', 'BigInt', 'BigDecimal'].includes(fieldType) || controlType == 'number' ? 'number' : 'string',
|
||||||
overHidden: isCardTable ? false : true,
|
overHidden: isCardTable ? false : true,
|
||||||
className: `low-field__${fieldCode} control-${controlType}`,
|
className: `low-field__${fieldCode} control-${controlType}`,
|
||||||
labelClassName: `low-header__${fieldCode}`
|
labelClassName: `low-header__${fieldCode}`,
|
||||||
|
sortNum: sortNum
|
||||||
}
|
}
|
||||||
|
|
||||||
//租户字段的列表、表单权限控制
|
//租户字段的列表、表单权限控制
|
||||||
|
|||||||
243
src/utils/indexedDB.ts
Normal file
243
src/utils/indexedDB.ts
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
/**
|
||||||
|
* IndexedDB 工具类
|
||||||
|
* 用于存储和读取表格列配置(显隐/冻结/过滤/排序)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const DB_NAME = 'lc_frontend_db'
|
||||||
|
const DB_VERSION = 1
|
||||||
|
const STORE_NAME = 'table_column_config'
|
||||||
|
|
||||||
|
let dbInstance: IDBDatabase | null = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开数据库并确保对象存储存在
|
||||||
|
*/
|
||||||
|
const openDBWithStore = (version: number): Promise<IDBDatabase> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const request = indexedDB.open(DB_NAME, version)
|
||||||
|
|
||||||
|
request.onerror = () => {
|
||||||
|
reject(request.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
request.onsuccess = () => {
|
||||||
|
const db = request.result
|
||||||
|
|
||||||
|
// 检查对象存储是否存在
|
||||||
|
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
||||||
|
// 对象存储不存在,需要升级数据库
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
// 用更高版本打开以触发升级
|
||||||
|
const upgradeRequest = indexedDB.open(DB_NAME, db.version + 1)
|
||||||
|
|
||||||
|
upgradeRequest.onerror = () => {
|
||||||
|
reject(upgradeRequest.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
upgradeRequest.onupgradeneeded = (event) => {
|
||||||
|
const upgradeDb = (event.target as IDBOpenDBRequest).result
|
||||||
|
// 如果对象存储不存在,创建它
|
||||||
|
if (!upgradeDb.objectStoreNames.contains(STORE_NAME)) {
|
||||||
|
upgradeDb.createObjectStore(STORE_NAME, { keyPath: 'key' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
upgradeRequest.onsuccess = () => {
|
||||||
|
resolve(upgradeRequest.result)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolve(db)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.onupgradeneeded = (event) => {
|
||||||
|
const db = (event.target as IDBOpenDBRequest).result
|
||||||
|
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
||||||
|
db.createObjectStore(STORE_NAME, { keyPath: 'key' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 IndexedDB
|
||||||
|
*/
|
||||||
|
const initDB = (): Promise<IDBDatabase> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (dbInstance) {
|
||||||
|
// 检查对象存储是否存在
|
||||||
|
if (dbInstance.objectStoreNames.contains(STORE_NAME)) {
|
||||||
|
resolve(dbInstance)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
// 对象存储不存在,需要重新初始化
|
||||||
|
dbInstance.close()
|
||||||
|
dbInstance = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先尝试获取当前数据库版本(不指定版本号打开)
|
||||||
|
const checkRequest = indexedDB.open(DB_NAME)
|
||||||
|
|
||||||
|
checkRequest.onsuccess = () => {
|
||||||
|
const checkDb = checkRequest.result
|
||||||
|
const currentVersion = checkDb.version
|
||||||
|
checkDb.close()
|
||||||
|
|
||||||
|
// 使用当前版本或更高版本打开
|
||||||
|
const targetVersion = Math.max(currentVersion, DB_VERSION)
|
||||||
|
openDBWithStore(targetVersion)
|
||||||
|
.then((db) => {
|
||||||
|
dbInstance = db
|
||||||
|
resolve(dbInstance)
|
||||||
|
})
|
||||||
|
.catch(reject)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkRequest.onerror = () => {
|
||||||
|
// 如果检查失败,直接使用默认版本尝试打开
|
||||||
|
openDBWithStore(DB_VERSION)
|
||||||
|
.then((db) => {
|
||||||
|
dbInstance = db
|
||||||
|
resolve(dbInstance)
|
||||||
|
})
|
||||||
|
.catch(reject)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列配置接口
|
||||||
|
*/
|
||||||
|
export interface ColumnConfig {
|
||||||
|
hide?: boolean
|
||||||
|
fixed?: string | boolean
|
||||||
|
sortable?: string | boolean
|
||||||
|
isShowColumn?: string // 'Y' 表示显示,'N' 表示隐藏
|
||||||
|
isExport?: string // 'Y' 表示导出,'N' 表示不导出
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存列配置
|
||||||
|
* @param key 唯一标识(通常是 route.params.id)
|
||||||
|
* @param config 列配置对象,格式:{ prop: { hide, fixed, sortable, isExport } }
|
||||||
|
*/
|
||||||
|
export const saveColumnConfig = async (key: string, config: Record<string, ColumnConfig>): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const db = await initDB()
|
||||||
|
const transaction = db.transaction([STORE_NAME], 'readwrite')
|
||||||
|
const store = transaction.objectStore(STORE_NAME)
|
||||||
|
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
const request = store.put({ key, config, updateTime: Date.now() })
|
||||||
|
request.onsuccess = () => resolve()
|
||||||
|
request.onerror = () => reject(request.error)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存列配置失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取列配置
|
||||||
|
* @param key 唯一标识(通常是 route.params.id)
|
||||||
|
* @returns 列配置对象,格式:{ prop: { hide, fixed, sortable, isExport } }
|
||||||
|
*/
|
||||||
|
export const getColumnConfig = async (key: string): Promise<Record<string, ColumnConfig> | null> => {
|
||||||
|
try {
|
||||||
|
const db = await initDB()
|
||||||
|
const transaction = db.transaction([STORE_NAME], 'readonly')
|
||||||
|
const store = transaction.objectStore(STORE_NAME)
|
||||||
|
|
||||||
|
return new Promise<Record<string, ColumnConfig> | null>((resolve, reject) => {
|
||||||
|
const request = store.get(key)
|
||||||
|
request.onsuccess = () => {
|
||||||
|
const result = request.result
|
||||||
|
resolve(result ? result.config : null)
|
||||||
|
}
|
||||||
|
request.onerror = () => reject(request.error)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('读取列配置失败:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除列配置
|
||||||
|
* @param key 唯一标识(通常是 route.params.id)
|
||||||
|
*/
|
||||||
|
export const deleteColumnConfig = async (key: string): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const db = await initDB()
|
||||||
|
const transaction = db.transaction([STORE_NAME], 'readwrite')
|
||||||
|
const store = transaction.objectStore(STORE_NAME)
|
||||||
|
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
const request = store.delete(key)
|
||||||
|
request.onsuccess = () => resolve()
|
||||||
|
request.onerror = () => reject(request.error)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除列配置失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存搜索区域显示状态
|
||||||
|
* @param key 唯一标识(通常是 route.params.id)
|
||||||
|
* @param visible 是否显示
|
||||||
|
*/
|
||||||
|
export const saveSearchVisible = async (key: string, visible: boolean): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const db = await initDB()
|
||||||
|
const transaction = db.transaction([STORE_NAME], 'readwrite')
|
||||||
|
const store = transaction.objectStore(STORE_NAME)
|
||||||
|
|
||||||
|
const data = await new Promise<any>((resolve, reject) => {
|
||||||
|
const request = store.get(key)
|
||||||
|
request.onsuccess = () => resolve(request.result)
|
||||||
|
request.onerror = () => reject(request.error)
|
||||||
|
})
|
||||||
|
|
||||||
|
const config = data?.config || {}
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
const request = store.put({
|
||||||
|
key,
|
||||||
|
config,
|
||||||
|
searchVisible: visible,
|
||||||
|
updateTime: Date.now()
|
||||||
|
})
|
||||||
|
request.onsuccess = () => resolve()
|
||||||
|
request.onerror = () => reject(request.error)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存搜索区域显示状态失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取搜索区域显示状态
|
||||||
|
* @param key 唯一标识(通常是 route.params.id)
|
||||||
|
* @returns 是否显示
|
||||||
|
*/
|
||||||
|
export const getSearchVisible = async (key: string): Promise<boolean | null> => {
|
||||||
|
try {
|
||||||
|
const db = await initDB()
|
||||||
|
const transaction = db.transaction([STORE_NAME], 'readonly')
|
||||||
|
const store = transaction.objectStore(STORE_NAME)
|
||||||
|
|
||||||
|
return new Promise<boolean | null>((resolve, reject) => {
|
||||||
|
const request = store.get(key)
|
||||||
|
request.onsuccess = () => {
|
||||||
|
const result = request.result
|
||||||
|
resolve(result && result.searchVisible !== undefined ? result.searchVisible : null)
|
||||||
|
}
|
||||||
|
request.onerror = () => reject(request.error)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('读取搜索区域显示状态失败:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user