fix bug
This commit is contained in:
1 parent
1609f19b9c
commit
37f4a99914
14 files changed
+953
-427
No files matched your search
@@ -5,38 +5,12 @@ import type { ColDef, GridOptions } from 'ag-grid-community'
|
||||
import localforage from 'localforage'
|
||||
import { majorList } from '@/sql'
|
||||
import 'ag-grid-enterprise'
|
||||
import {
|
||||
import { myTheme } from '@/lib/diyAgGridTheme'
|
||||
|
||||
themeQuartz
|
||||
} from "ag-grid-community"
|
||||
import { AG_GRID_LOCALE_CN } from '@ag-grid-community/locale';
|
||||
// 精简的边框配置(细线条+浅灰色,弱化分割线视觉)
|
||||
const borderConfig = {
|
||||
style: "solid", // 虚线改实线更简洁,也可保留 dotted 但建议用 solid
|
||||
width: 0.5, // 更细的边框,减少视觉干扰
|
||||
color: "#e5e7eb" // 浅灰色边框,清新不刺眼
|
||||
};
|
||||
|
||||
// 简洁清新风格的主题配置
|
||||
const myTheme = themeQuartz.withParams({
|
||||
// 核心:移除外边框,减少视觉包裹感
|
||||
wrapperBorder: false,
|
||||
|
||||
// 表头样式(柔和浅蓝,无加粗,更轻盈)
|
||||
headerBackgroundColor: "#f9fafb", // 极浅的背景色,替代深一点的 #e7f3fc
|
||||
headerTextColor: "#374151", // 深灰色文字,比纯黑更柔和
|
||||
headerFontSize: 15, // 字体稍大一点,更易读
|
||||
headerFontWeight: "normal", // 取消加粗,降低视觉重量
|
||||
|
||||
// 行/列/表头边框(统一浅灰细边框)
|
||||
rowBorder: borderConfig,
|
||||
columnBorder: borderConfig,
|
||||
headerRowBorder: borderConfig,
|
||||
|
||||
|
||||
// 可选:偶数行背景色(轻微区分,更清新)
|
||||
dataBackgroundColor: "#fefefe"
|
||||
});
|
||||
interface DictLeaf {
|
||||
id: string
|
||||
code: string
|
||||
@@ -71,6 +45,73 @@ const DEFAULT_PROJECT_NAME = 'xxx造价咨询服务'
|
||||
|
||||
const projectName = ref(DEFAULT_PROJECT_NAME)
|
||||
const detailRows = ref<DetailRow[]>([])
|
||||
const rootRef = ref<HTMLElement | null>(null)
|
||||
const gridSectionRef = ref<HTMLElement | null>(null)
|
||||
const agGridRef = ref<HTMLElement | null>(null)
|
||||
const agGridHeight = ref(580)
|
||||
let snapScrollHost: HTMLElement | null = null
|
||||
let snapTimer: ReturnType<typeof setTimeout> | null = null
|
||||
let snapLockTimer: ReturnType<typeof setTimeout> | null = null
|
||||
let isSnapping = false
|
||||
let hostResizeObserver: ResizeObserver | null = null
|
||||
|
||||
const updateGridCardHeight = () => {
|
||||
if (!snapScrollHost || !rootRef.value) return
|
||||
const contentWrap = rootRef.value.parentElement
|
||||
const style = contentWrap ? window.getComputedStyle(contentWrap) : null
|
||||
const paddingTop = style ? Number.parseFloat(style.paddingTop || '0') || 0 : 0
|
||||
const paddingBottom = style ? Number.parseFloat(style.paddingBottom || '0') || 0 : 0
|
||||
const nextHeight = Math.max(360, Math.floor(snapScrollHost.clientHeight - paddingTop - paddingBottom))
|
||||
agGridHeight.value = nextHeight
|
||||
}
|
||||
|
||||
const bindSnapScrollHost = () => {
|
||||
snapScrollHost = rootRef.value?.closest('[data-slot="scroll-area-viewport"]') as HTMLElement | null
|
||||
if (!snapScrollHost) return
|
||||
snapScrollHost.addEventListener('scroll', handleSnapHostScroll, { passive: true })
|
||||
hostResizeObserver?.disconnect()
|
||||
hostResizeObserver = new ResizeObserver(() => {
|
||||
updateGridCardHeight()
|
||||
})
|
||||
hostResizeObserver.observe(snapScrollHost)
|
||||
updateGridCardHeight()
|
||||
}
|
||||
|
||||
const unbindSnapScrollHost = () => {
|
||||
if (snapScrollHost) {
|
||||
snapScrollHost.removeEventListener('scroll', handleSnapHostScroll)
|
||||
}
|
||||
hostResizeObserver?.disconnect()
|
||||
hostResizeObserver = null
|
||||
snapScrollHost = null
|
||||
}
|
||||
|
||||
const trySnapToGrid = () => {
|
||||
if (isSnapping || !snapScrollHost || !agGridRef.value) return
|
||||
|
||||
const hostRect = snapScrollHost.getBoundingClientRect()
|
||||
const gridRect = agGridRef.value.getBoundingClientRect()
|
||||
const offsetTop = gridRect.top - hostRect.top
|
||||
const inVisibleBand = gridRect.bottom > hostRect.top + 40 && gridRect.top < hostRect.bottom - 40
|
||||
const inSnapRange = offsetTop > -120 && offsetTop < 180
|
||||
|
||||
if (!inVisibleBand || !inSnapRange) return
|
||||
|
||||
isSnapping = true
|
||||
agGridRef.value.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||
if (snapLockTimer) clearTimeout(snapLockTimer)
|
||||
snapLockTimer = setTimeout(() => {
|
||||
isSnapping = false
|
||||
}, 420)
|
||||
}
|
||||
|
||||
function handleSnapHostScroll() {
|
||||
if (isSnapping) return
|
||||
if (snapTimer) clearTimeout(snapTimer)
|
||||
snapTimer = setTimeout(() => {
|
||||
trySnapToGrid()
|
||||
}, 90)
|
||||
}
|
||||
type MajorLite = { code: string; name: string }
|
||||
const majorEntries = Object.entries(majorList as Record<string, MajorLite>)
|
||||
.sort((a, b) => Number(a[0]) - Number(b[0]))
|
||||
@@ -330,13 +371,20 @@ watch(projectName, schedulePersist)
|
||||
|
||||
onMounted(async () => {
|
||||
await loadFromIndexedDB()
|
||||
bindSnapScrollHost()
|
||||
requestAnimationFrame(() => {
|
||||
updateGridCardHeight()
|
||||
})
|
||||
// window.addEventListener('beforeunload', handleBeforeUnload)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// window.removeEventListener('beforeunload', handleBeforeUnload)
|
||||
unbindSnapScrollHost()
|
||||
if (persistTimer) clearTimeout(persistTimer)
|
||||
if (gridPersistTimer) clearTimeout(gridPersistTimer)
|
||||
if (snapTimer) clearTimeout(snapTimer)
|
||||
if (snapLockTimer) clearTimeout(snapLockTimer)
|
||||
void saveToIndexedDB()
|
||||
})
|
||||
const processCellForClipboard = (params:any) => {
|
||||
@@ -358,9 +406,11 @@ const processCellFromClipboard = (params:any) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-6">
|
||||
<div class="rounded-lg border bg-card p-4 shadow-sm">
|
||||
<label class="mb-2 block text-sm font-medium text-foreground">项目名称</label>
|
||||
<div ref="rootRef" class="space-y-6">
|
||||
<div class="rounded-lg border bg-card p-4 shadow-sm shrink-0">
|
||||
<div class="mb-2 flex items-center justify-between gap-3">
|
||||
<label class="block text-sm font-medium text-foreground">项目名称</label>
|
||||
</div>
|
||||
<input
|
||||
v-model="projectName"
|
||||
type="text"
|
||||
@@ -369,13 +419,16 @@ const processCellFromClipboard = (params:any) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="rounded-lg border bg-card xmMx">
|
||||
<div
|
||||
ref="gridSectionRef"
|
||||
class="rounded-lg border bg-card xmMx scroll-mt-3"
|
||||
>
|
||||
<div class="flex items-center justify-between border-b px-4 py-3">
|
||||
<h3 class="text-sm font-semibold text-foreground">项目明细</h3>
|
||||
<div class="text-xs text-muted-foreground">导入导出</div>
|
||||
</div>
|
||||
|
||||
<div class="ag-theme-quartz h-[580px] w-full">
|
||||
<div ref="agGridRef" class="ag-theme-quartz w-full" :style="{ height: `${agGridHeight}px` }">
|
||||
<AgGridVue
|
||||
:style="{ height: '100%' }"
|
||||
:rowData="detailRows"
|
||||
|
||||
Reference in new issue
Block a user