Pārlūkot izejas kodu

缩放改好-修改样式1

qdy 1 mēnesi atpakaļ
vecāks
revīzija
72f5fec6d7

+ 0
- 69
src/app/components/sticky-header/sticky-header.component.html Parādīt failu

@@ -1,69 +0,0 @@
1
-<div class="sticky-header sticky top-0 z-10 transition-all duration-300 ease-in-out" [style.min-height]="headerHeight" [class.locked]="isLocked" [class.compact]="isCompact" [ngStyle]="isLocked ? {
2
-  width: headerWidth ? (typeof headerWidth === 'number' ? headerWidth + 'px' : headerWidth) : null,
3
-  left: headerLeft ? (typeof headerLeft === 'number' ? headerLeft + 'px' : headerLeft) : null
4
-} : null">
5
-  <!-- 主标题区域 -->
6
-  <div class="header-content bg-white rounded-lg border border-gray-200 shadow-sm transition-all duration-300">
7
-    <div class="flex justify-between items-center p-4 transition-all duration-300">
8
-      <h1 class="header-title text-2xl font-bold transition-all duration-300">{{ title }}</h1>
9
-      <button 
10
-        mat-raised-button 
11
-        [color]="buttonColor" 
12
-        (click)="onButtonClick()" 
13
-        [disabled]="disabled || loading"
14
-        class="flex items-center gap-2"
15
-      >
16
-        <mat-icon *ngIf="!loading">{{ buttonIcon }}</mat-icon>
17
-        <mat-progress-spinner 
18
-          *ngIf="loading" 
19
-          diameter="20" 
20
-          mode="indeterminate" 
21
-          class="inline-block"
22
-        ></mat-progress-spinner>
23
-        {{ loading ? '处理中...' : buttonText }}
24
-       </button>
25
-    </div>
26
-    
27
-    <!-- 提示信息 -->
28
-    @if (hintText) {
29
-      <div class="hint-section border-t border-gray-100 p-3 bg-blue-50/30 transition-all duration-300 overflow-hidden">
30
-        <p class="text-sm text-gray-600 m-0 transition-all duration-300">{{ hintText }}</p>
31
-      </div>
32
-    }
33
-    
34
-    <!-- 调试信息区域 -->
35
-    @if (showDebugInfo && (debugDataSource || debugRegisterUrl || debugListUrl)) {
36
-      <div class="debug-section border-t border-gray-100 overflow-hidden">
37
-        <!-- 数据源信息 -->
38
-        @if (debugDataSource) {
39
-          <div class="debug-info text-xs text-gray-500 p-2 bg-gray-50 transition-all duration-300">
40
-            <div class="flex gap-4 flex-wrap transition-all duration-300">
41
-              <span>数据源: <span class="font-mono">{{ debugDataSource }}</span></span>
42
-              <span>记录条数: <span class="font-mono">{{ debugRecordCount }}</span></span>
43
-              <span>更新时间: <span class="font-mono">{{ debugLastUpdated }}</span></span>
44
-              @if (debugUseMockData) {
45
-                <span class="text-amber-600 font-medium">⚠ 使用模拟数据</span>
46
-              } @else {
47
-                <span class="text-green-600 font-medium">✓ 使用API数据</span>
48
-              }
49
-            </div>
50
-          </div>
51
-        }
52
-        
53
-        <!-- API URL信息 -->
54
-        @if (debugRegisterUrl || debugListUrl) {
55
-          <div class="debug-urls text-xs text-gray-500 p-2 bg-gray-50 border-t border-gray-100 transition-all duration-300">
56
-            <div class="flex flex-col gap-1 transition-all duration-300">
57
-              @if (debugRegisterUrl) {
58
-                <span>注册API: <span class="font-mono">{{ debugRegisterUrl || '未调用' }}</span></span>
59
-              }
60
-              @if (debugListUrl) {
61
-                <span>列表API: <span class="font-mono">{{ debugListUrl || '未调用' }}</span></span>
62
-              }
63
-            </div>
64
-          </div>
65
-        }
66
-      </div>
67
-    }
68
-  </div>
69
-</div>

+ 0
- 166
src/app/components/sticky-header/sticky-header.component.scss Parādīt failu

@@ -1,166 +0,0 @@
1
-.sticky-header {
2
-  position: sticky;
3
-  top: 0;
4
-  z-index: 1000; /* 进一步提高z-index确保在最顶部 */
5
-  transition: all 0.3s ease-in-out;
6
-  margin-bottom: 1.5rem; /* 为内容区域提供间距 */
7
-  align-self: flex-start; /* 确保在flex容器中sticky生效 */
8
-  background-color: white; /* 确保不透明,防止内容透出 */
9
-  /* 创建新的层叠上下文,确保z-index生效 */
10
-  transform: translateZ(0);
11
-  will-change: transform;
12
-  /* 轻微的内阴影,增强立体感 */
13
-  box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.8);
14
-
15
-  .header-content {
16
-    background: #f8fafc; /* 简洁的灰白色背景 */
17
-    border-radius: 0.5rem;
18
-    border: 1px solid #e2e8f0; /* 柔和的边框 */
19
-    box-shadow: 
20
-      inset 0 2px 4px 0 rgba(0, 0, 0, 0.06), /* 轻微内阴影,创造凹陷感 */
21
-      inset 0 0 0 1px rgba(255, 255, 255, 0.9), /* 内边缘高光,增强立体感 */
22
-      0 1px 2px 0 rgba(0, 0, 0, 0.05); /* 轻微外阴影,保持与页面融合 */
23
-    transition: all 0.3s ease-in-out;
24
-    height: 100%; /* 填充父容器高度 */
25
-    min-height: 100%; /* 确保填充最小高度 */
26
-    /* 移除 overflow: hidden,防止内容裁剪 */
27
-  }
28
-
29
-  .header-title {
30
-    font-size: 1.75rem; /* text-3xl */
31
-    font-weight: 800;
32
-    transition: all 0.3s ease-in-out;
33
-    margin: 0;
34
-    color: #1e293b; /* text-slate-800 */
35
-    text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8); /* 轻微文字阴影,增强可读性 */
36
-  }
37
-
38
-  .debug-section {
39
-    transition: all 0.3s ease-in-out;
40
-    max-height: 200px;
41
-    opacity: 1;
42
-    
43
-    .debug-info, .debug-urls {
44
-      &:not(:last-child) {
45
-        border-bottom: 1px solid #e2e8f0; /* border-slate-200 */
46
-      }
47
-    }
48
-  }
49
-
50
-  .hint-section {
51
-    transition: all 0.3s ease-in-out;
52
-    max-height: 100px;
53
-    opacity: 1;
54
-  }
55
-
56
-  /* 锁定状态 - 固定在视口顶部,保持原大小 */
57
-  &.locked {
58
-    position: fixed;
59
-    top: 0;
60
-    z-index: 1100; /* 提高z-index确保在最顶层 */
61
-    margin-bottom: 0; /* 移除margin,因为现在是fixed定位 */
62
-    transform: none; /* 移除transform层叠上下文 */
63
-    will-change: auto;
64
-    box-shadow: none; /* 移除外阴影,增强一体感 */
65
-    background-color: white; /* 确保背景不透明 */
66
-    
67
-    .header-content {
68
-      border-radius: 0.5rem;
69
-      box-shadow: 
70
-        inset 0 2px 4px 0 rgba(0, 0, 0, 0.06),
71
-        inset 0 0 0 1px rgba(255, 255, 255, 0.9); /* 内阴影,增强一体感 */
72
-      background: #f1f5f9;
73
-      border: 1px solid #cbd5e1;
74
-      margin: 0; /* 移除外边距,确保精确对齐 */
75
-      height: 100%; /* 填充父容器高度 */
76
-      min-height: 100%; /* 确保填充最小高度 */
77
-      /* 保持原padding大小 */
78
-    }
79
-
80
-    .header-title {
81
-      /* 保持原字体大小:1.75rem */
82
-      font-weight: 800;
83
-      color: #1e293b;
84
-      text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
85
-    }
86
-
87
-    .hint-section {
88
-      max-height: 0;
89
-      opacity: 0;
90
-      padding-top: 0;
91
-      padding-bottom: 0;
92
-      border: none;
93
-      
94
-      p {
95
-        font-size: 0.8125rem;
96
-        opacity: 0;
97
-      }
98
-    }
99
-    
100
-    .debug-section {
101
-      max-height: 0;
102
-      opacity: 0;
103
-      
104
-      .debug-info, .debug-urls {
105
-        padding-top: 0;
106
-        padding-bottom: 0;
107
-        font-size: 0.6875rem;
108
-        opacity: 0;
109
-        border: none;
110
-      }
111
-    }
112
-  }
113
-
114
-  /* 缩小状态 - 在锁定基础上进一步缩小 */
115
-  &.compact {
116
-    .header-content {
117
-      border-radius: 0.375rem;
118
-      box-shadow: 
119
-        inset 0 3px 6px 0 rgba(0, 0, 0, 0.08), /* 更强的内阴影,增强凹陷感 */
120
-        inset 0 0 0 1px rgba(255, 255, 255, 0.8); /* 内边缘高光,增强一体感 */
121
-      background: #f1f5f9; /* 稍微深一点的背景,强调状态变化 */
122
-      border: 1px solid #cbd5e1; /* 保持一致的边框 */
123
-      height: 100%; /* 填充父容器高度 */
124
-      min-height: 100%; /* 确保填充最小高度 */
125
-      
126
-      > div:first-child {
127
-        padding-top: 0.375rem;
128
-        padding-bottom: 0.375rem;
129
-      }
130
-    }
131
-
132
-    .header-title {
133
-      font-size: 1.125rem; /* 更小一点 */
134
-      font-weight: 800;
135
-      color: #0f172a; /* 更深的文字颜色,增强可读性 */
136
-      text-shadow: 0 1px 2px rgba(255, 255, 255, 0.9); /* 保持文字阴影 */
137
-      letter-spacing: -0.025em; /* 紧凑的字母间距 */
138
-    }
139
-
140
-    .hint-section {
141
-      max-height: 0;
142
-      opacity: 0;
143
-      padding-top: 0;
144
-      padding-bottom: 0;
145
-      border: none;
146
-      
147
-      p {
148
-        font-size: 0.8125rem; /* 比text-sm小一点 */
149
-        opacity: 0;
150
-      }
151
-    }
152
-    
153
-    .debug-section {
154
-      max-height: 0;
155
-      opacity: 0;
156
-      
157
-      .debug-info, .debug-urls {
158
-        padding-top: 0;
159
-        padding-bottom: 0;
160
-        font-size: 0.6875rem; /* 比text-xs更小 */
161
-        opacity: 0;
162
-        border: none;
163
-      }
164
-    }
165
-  }
166
-}

+ 0
- 499
src/app/components/sticky-header/sticky-header.component.ts Parādīt failu

@@ -1,499 +0,0 @@
1
-import { Component, Input, Output, EventEmitter, AfterViewInit, OnDestroy, Renderer2, Inject, ElementRef } from '@angular/core';
2
-import { CommonModule } from '@angular/common';
3
-import { MatButtonModule } from '@angular/material/button';
4
-import { MatIconModule } from '@angular/material/icon';
5
-import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
6
-
7
-@Component({
8
-  selector: 'app-sticky-header',
9
-  standalone: true,
10
-  imports: [CommonModule, MatButtonModule, MatIconModule, MatProgressSpinnerModule],
11
-  templateUrl: './sticky-header.component.html',
12
-  styleUrl: './sticky-header.component.scss'
13
-})
14
-export class StickyHeaderComponent implements AfterViewInit, OnDestroy {
15
-   constructor(
16
-    private renderer: Renderer2,
17
-    private elementRef: ElementRef
18
-  ) {}
19
-  
20
-  // 滚动优化相关属性
21
-  private scrollRafId: number | null = null;
22
-  private lastScrollTop = 0;
23
-  private lastIsLocked = false;
24
-  private lastIsCompact = false;
25
-  
26
-  /** 标题文本 */
27
-  @Input() title = '';
28
-  
29
-  /** 按钮文本 */
30
-  @Input() buttonText = '操作';
31
-  
32
-  /** 按钮图标 */
33
-  @Input() buttonIcon = 'add';
34
-  
35
-  /** 按钮颜色,默认primary */
36
-  @Input() buttonColor: 'primary' | 'accent' | 'warn' = 'primary';
37
-  
38
-  /** 是否禁用按钮 */
39
-  @Input() disabled = false;
40
-  
41
-  /** 是否显示加载状态 */
42
-  @Input() loading = false;
43
-  
44
-  /** 滚动阈值(像素),默认为5 */
45
-  @Input() scrollThreshold = 5;
46
-
47
-  /** 是否启用自动滚动检测 */
48
-  @Input() autoDetect = false;
49
-
50
-  /** 滚动容器选择器,默认为'.content-area',设为'window'监听窗口滚动 */
51
-  @Input() scrollContainer = '.content-area';
52
-
53
-  /** 紧凑模式阈值(像素),默认为50 */
54
-  @Input() compactThreshold = 50;
55
-
56
-  /** 是否显示调试信息框 */
57
-  @Input() showDebugInfo = false;
58
-  
59
-  /** 调试信息数据源 */
60
-  @Input() debugDataSource = '';
61
-  
62
-  /** 调试信息记录数 */
63
-  @Input() debugRecordCount = 0;
64
-  
65
-  /** 调试信息更新时间 */
66
-  @Input() debugLastUpdated = '';
67
-  
68
-  /** 调试信息是否使用模拟数据 */
69
-  @Input() debugUseMockData = false;
70
-  
71
-  /** 调试信息注册API URL */
72
-  @Input() debugRegisterUrl = '';
73
-  
74
-  /** 调试信息列表API URL */
75
-  @Input() debugListUrl = '';
76
-
77
-  /** 提示文本,显示在标题下方 */
78
-  @Input() hintText = '';
79
-
80
-  /** 是否已滚动(由父组件控制,向后兼容) */
81
-  @Input() isScrolled = false;
82
-
83
-  /** 是否锁定在顶部(到达滚动容器顶部) */
84
-  @Input() isLocked = false;
85
-
86
-  /** 是否缩小状态(锁定后进一步缩小) */
87
-  @Input() isCompact = false;
88
-
89
-  /** 锁定时的宽度(像素或百分比) */
90
-  @Input() headerWidth: string | number | null = null;
91
-
92
-  /** 锁定时的左侧偏移(像素) */
93
-  @Input() headerLeft: string | number | null = null;
94
-
95
-  /** 宽度参考目标选择器(用于锁定状态宽度匹配),如未设置则使用滚动容器 */
96
-  @Input() widthTarget: string | null = null;
97
-
98
-  /** 标题区域最小高度(用于测试或固定高度布局),如 '200px', '10rem',未设置则由内容决定 */
99
-  @Input() headerHeight: string | null = null;
100
-
101
-  /** 按钮点击事件 */
102
-  @Output() buttonClick = new EventEmitter<void>();
103
-
104
-  // 自动滚动检测的私有属性
105
-  private scrollListener: (() => void) | null = null;
106
-  private canScroll = false;
107
-  private isAutoDetecting = false;
108
-
109
-  onButtonClick() {
110
-    if (!this.disabled && !this.loading) {
111
-      this.buttonClick.emit();
112
-    }
113
-  }
114
-
115
-  ngAfterViewInit() {
116
-    if (this.autoDetect) {
117
-      this.setupAutoScrollDetection();
118
-    }
119
-  }
120
-
121
-   ngOnDestroy() {
122
-    this.cleanupScrollListener();
123
-    if (this.scrollRafId) {
124
-      cancelAnimationFrame(this.scrollRafId);
125
-      this.scrollRafId = null;
126
-    }
127
-  }
128
-
129
-  private setupAutoScrollDetection() {
130
-    if (this.isAutoDetecting) return;
131
-    
132
-    this.isAutoDetecting = true;
133
-    const container = this.getScrollContainer();
134
-    const isWindowScroll = this.scrollContainer === 'window';
135
-    
136
-     if (isWindowScroll) {
137
-      // 窗口滚动
138
-      this.canScroll = this.checkWindowScrollable();
139
-      const scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight || 0;
140
-      const clientHeight = window.innerHeight || document.documentElement.clientHeight || 0;
141
-      
142
-      console.log(`sticky-header: 窗口滚动性检查 - scrollHeight: ${scrollHeight}, clientHeight: ${clientHeight}, canScroll: ${this.canScroll}`);
143
-      
144
-      if (this.canScroll) {
145
-        this.scrollListener = this.renderer.listen(
146
-          'window',
147
-          'scroll',
148
-          this.handleWindowScroll.bind(this)
149
-        );
150
-        console.log('sticky-header: 自动滚动检测已启用,窗口滚动');
151
-        
152
-        // 初始检查窗口滚动位置
153
-        this.checkInitialWindowScrollPosition();
154
-      } else {
155
-        console.log('sticky-header: 窗口内容不足,禁用自动检测,设置isLocked=false, isCompact=false');
156
-        this.isLocked = false;
157
-        this.isCompact = false;
158
-        this.isScrolled = false;
159
-      }
160
-     } else if (container) {
161
-      // 容器滚动
162
-      this.canScroll = this.checkScrollable(container);
163
-      const scrollHeight = container.scrollHeight || 0;
164
-      const clientHeight = container.clientHeight || 0;
165
-      
166
-      console.log(`sticky-header: 容器滚动性检查 - scrollHeight: ${scrollHeight}, clientHeight: ${clientHeight}, canScroll: ${this.canScroll}, selector: ${this.scrollContainer}`);
167
-      
168
-      if (this.canScroll) {
169
-        this.scrollListener = this.renderer.listen(
170
-          container,
171
-          'scroll',
172
-          this.handleScroll.bind(this)
173
-        );
174
-        console.log('sticky-header: 自动滚动检测已启用,容器:', this.scrollContainer);
175
-        
176
-        // 初始检查滚动位置
177
-        this.checkInitialScrollPosition(container);
178
-      } else {
179
-        console.log('sticky-header: 滚动容器内容不足,禁用自动检测,设置isLocked=false, isCompact=false');
180
-        // 确保状态为false
181
-        this.isLocked = false;
182
-        this.isCompact = false;
183
-        this.isScrolled = false;
184
-      }
185
-    } else {
186
-      console.warn('sticky-header: 未找到滚动容器:', this.scrollContainer);
187
-    }
188
-  }
189
-
190
-  private getScrollContainer(): HTMLElement | null {
191
-    if (this.scrollContainer === 'window') {
192
-      return null; // 表示窗口滚动
193
-    }
194
-    
195
-    // 从当前元素向上查找最近的匹配容器
196
-    const container = this.elementRef.nativeElement.closest(this.scrollContainer);
197
-    if (container) {
198
-      return container;
199
-    }
200
-    
201
-    // 全局查找
202
-    return document.querySelector(this.scrollContainer) as HTMLElement;
203
-  }
204
-
205
-  private checkScrollable(container: HTMLElement): boolean {
206
-    if (!container) return false;
207
-    
208
-    const scrollHeight = container.scrollHeight || 0;
209
-    const clientHeight = container.clientHeight || 0;
210
-    
211
-    // 如果内容高度大于可视区域高度,说明可以滚动
212
-    // 添加5px容差,避免因计算误差导致的误判
213
-    const canScroll = scrollHeight > clientHeight + 5;
214
-    return canScroll;
215
-  }
216
-
217
-   private checkWindowScrollable(): boolean {
218
-    const scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight || 0;
219
-    const clientHeight = window.innerHeight || document.documentElement.clientHeight || 0;
220
-    
221
-    const canScroll = scrollHeight > clientHeight + 5;
222
-    return canScroll;
223
-  }
224
-
225
-   private findContentContainer(): HTMLElement | null {
226
-    // 尝试查找内容区域容器,优先级:
227
-    // 1. .content-area 类 (我们在app.component.html中添加的)
228
-    // 2. 包含router-outlet的容器
229
-    // 3. 右侧内容区域
230
-    const selectors = [
231
-      '.content-area',
232
-      '.flex-1.overflow-auto',
233
-      'div[class*="content"]',
234
-      'div[class*="main"]',
235
-      'div[class*="container"]'
236
-    ];
237
-    
238
-    for (const selector of selectors) {
239
-      const container = document.querySelector(selector) as HTMLElement;
240
-      if (container) {
241
-        console.log(`sticky-header: 找到内容容器: ${selector}, 位置: ${container.getBoundingClientRect().left}px, 宽度: ${container.getBoundingClientRect().width}px`);
242
-        return container;
243
-      }
244
-    }
245
-    
246
-    console.warn('sticky-header: 未找到内容容器');
247
-    return null;
248
-  }
249
-
250
-  private getWidthTargetElement(): HTMLElement | null {
251
-    // 如果设置了widthTarget,优先使用它
252
-    if (this.widthTarget) {
253
-      const target = document.querySelector(this.widthTarget) as HTMLElement;
254
-      if (target) {
255
-        console.log(`sticky-header: 找到宽度目标元素: ${this.widthTarget}, 宽度: ${target.getBoundingClientRect().width}px`);
256
-        return target;
257
-      }
258
-      console.warn(`sticky-header: 未找到宽度目标元素: ${this.widthTarget}`);
259
-    }
260
-    
261
-    // 否则根据滚动容器类型返回相应元素
262
-    if (this.scrollContainer === 'window') {
263
-      return this.findContentContainer();
264
-    } else {
265
-      const container = this.getScrollContainer();
266
-      return container;
267
-    }
268
-  }
269
-
270
-  private getSidebarWidth(): number {
271
-    // 从localStorage读取侧边栏宽度,默认320px
272
-    try {
273
-      const savedWidth = localStorage.getItem('sidebarWidth');
274
-      if (savedWidth) {
275
-        const width = parseInt(savedWidth, 10);
276
-        if (!isNaN(width) && width >= 200 && width <= 600) {
277
-          return width;
278
-        }
279
-      }
280
-    } catch (e) {
281
-      console.warn('sticky-header: 读取侧边栏宽度失败', e);
282
-    }
283
-    return 320; // 默认宽度
284
-  }
285
-
286
-    private handleWindowScroll() {
287
-    // 如果窗口不可滚动,不处理滚动事件
288
-    if (!this.canScroll) {
289
-      console.log('sticky-header: 窗口不可滚动,跳过处理');
290
-      return;
291
-    }
292
-    
293
-    // 使用requestAnimationFrame防抖,避免频繁更新
294
-    if (this.scrollRafId) {
295
-      cancelAnimationFrame(this.scrollRafId);
296
-    }
297
-    
298
-    this.scrollRafId = requestAnimationFrame(() => {
299
-      this.scrollRafId = null;
300
-      
301
-      const scrollTop = window.scrollY || document.documentElement.scrollTop || 0;
302
-      
303
-      // 检查滚动位置是否显著变化,避免微小滚动触发状态更新
304
-      const scrollDelta = Math.abs(scrollTop - this.lastScrollTop);
305
-      if (scrollDelta < 1) { // 小于1像素的变化忽略
306
-        return;
307
-      }
308
-      
309
-      this.lastScrollTop = scrollTop;
310
-      
311
-      // 计算新状态
312
-      const newIsScrolled = scrollTop > this.scrollThreshold;
313
-      const newIsLocked = scrollTop > this.scrollThreshold;
314
-      const newIsCompact = scrollTop > this.compactThreshold;
315
-      
316
-      // 检查状态是否真正变化,避免不必要更新
317
-      const stateChanged = 
318
-        newIsLocked !== this.lastIsLocked || 
319
-        newIsCompact !== this.lastIsCompact ||
320
-        newIsScrolled !== this.isScrolled;
321
-      
322
-      if (!stateChanged) {
323
-        console.log(`sticky-header: 滚动位置变化但状态未变,scrollTop=${scrollTop}, isLocked=${newIsLocked}, isCompact=${newIsCompact}`);
324
-        return;
325
-      }
326
-      
327
-      this.lastIsLocked = newIsLocked;
328
-      this.lastIsCompact = newIsCompact;
329
-      
330
-      // 更新滚动状态
331
-      this.isScrolled = newIsScrolled;
332
-      this.isLocked = newIsLocked;
333
-      this.isCompact = newIsCompact;
334
-      
335
-      console.log(`sticky-header: 滚动状态更新,scrollTop=${scrollTop}, isLocked=${this.isLocked}, isCompact=${this.isCompact}`);
336
-      
337
-      // 设置宽度匹配容器
338
-      if (this.isLocked) {
339
-        // 使用宽度目标元素计算宽度
340
-        const widthTargetElement = this.getWidthTargetElement();
341
-        if (widthTargetElement) {
342
-          const rect = widthTargetElement.getBoundingClientRect();
343
-          this.headerWidth = rect.width;
344
-          this.headerLeft = rect.left;
345
-          console.log(`sticky-header: 窗口滚动锁定,目标宽度: ${rect.width}px, 左侧位置: ${rect.left}px, 目标元素: ${this.widthTarget || '默认'}`);
346
-        } else {
347
-          // 回退:使用视口宽度减去实际侧边栏宽度
348
-          const sidebarWidth = this.getSidebarWidth();
349
-          this.headerWidth = `calc(100% - ${sidebarWidth}px)`;
350
-          this.headerLeft = sidebarWidth;
351
-          console.log(`sticky-header: 未找到宽度目标元素,使用回退宽度: ${this.headerWidth}, 侧边栏宽度: ${sidebarWidth}px`);
352
-        }
353
-      } else {
354
-        this.headerWidth = null;
355
-        this.headerLeft = null;
356
-      }
357
-    });
358
-  }
359
-
360
-    private checkInitialWindowScrollPosition() {
361
-    const scrollTop = window.scrollY || document.documentElement.scrollTop || 0;
362
-    this.lastScrollTop = scrollTop;
363
-    
364
-    this.isScrolled = scrollTop > this.scrollThreshold;
365
-    this.isLocked = scrollTop > this.scrollThreshold;
366
-    this.isCompact = scrollTop > this.compactThreshold;
367
-    
368
-    // 记录初始状态
369
-    this.lastIsLocked = this.isLocked;
370
-    this.lastIsCompact = this.isCompact;
371
-    
372
-    if (this.isLocked) {
373
-      // 使用宽度目标元素计算宽度
374
-      const widthTargetElement = this.getWidthTargetElement();
375
-      if (widthTargetElement) {
376
-        const rect = widthTargetElement.getBoundingClientRect();
377
-        this.headerWidth = rect.width;
378
-        this.headerLeft = rect.left;
379
-        console.log(`sticky-header: 初始窗口滚动位置检查: scrollTop=${scrollTop}, isLocked=${this.isLocked}, isCompact=${this.isCompact}, 目标宽度: ${rect.width}px, 目标元素: ${this.widthTarget || '默认'}`);
380
-      } else {
381
-        // 回退:使用视口宽度减去实际侧边栏宽度
382
-        const sidebarWidth = this.getSidebarWidth();
383
-        this.headerWidth = `calc(100% - ${sidebarWidth}px)`;
384
-        this.headerLeft = sidebarWidth;
385
-        console.log(`sticky-header: 初始窗口滚动位置检查: scrollTop=${scrollTop}, isLocked=${this.isLocked}, isCompact=${this.isCompact}, 使用回退宽度`);
386
-      }
387
-    } else {
388
-      this.headerWidth = null;
389
-      this.headerLeft = null;
390
-    }
391
-    
392
-    console.log(`sticky-header: 初始窗口滚动位置检查完成: scrollTop=${scrollTop}, isLocked=${this.isLocked}, isCompact=${this.isCompact}, canScroll=${this.canScroll}`);
393
-  }
394
-
395
-   private handleScroll(event: Event) {
396
-    // 如果容器不可滚动,不处理滚动事件
397
-    if (!this.canScroll) {
398
-      console.log('sticky-header: 容器不可滚动,跳过处理');
399
-      return;
400
-    }
401
-    
402
-    // 使用requestAnimationFrame防抖,避免频繁更新
403
-    if (this.scrollRafId) {
404
-      cancelAnimationFrame(this.scrollRafId);
405
-    }
406
-    
407
-    this.scrollRafId = requestAnimationFrame(() => {
408
-      this.scrollRafId = null;
409
-      
410
-      const container = event.target as HTMLElement;
411
-      const scrollTop = container.scrollTop || 0;
412
-      
413
-      // 检查滚动位置是否显著变化,避免微小滚动触发状态更新
414
-      const scrollDelta = Math.abs(scrollTop - this.lastScrollTop);
415
-      if (scrollDelta < 1) { // 小于1像素的变化忽略
416
-        return;
417
-      }
418
-      
419
-      this.lastScrollTop = scrollTop;
420
-      
421
-      // 计算新状态
422
-      const newIsScrolled = scrollTop > this.scrollThreshold;
423
-      const newIsLocked = scrollTop > this.scrollThreshold;
424
-      const newIsCompact = scrollTop > this.compactThreshold;
425
-      
426
-      // 检查状态是否真正变化,避免不必要更新
427
-      const stateChanged = 
428
-        newIsLocked !== this.lastIsLocked || 
429
-        newIsCompact !== this.lastIsCompact ||
430
-        newIsScrolled !== this.isScrolled;
431
-      
432
-      if (!stateChanged) {
433
-        console.log(`sticky-header: 容器滚动位置变化但状态未变,scrollTop=${scrollTop}, isLocked=${newIsLocked}, isCompact=${newIsCompact}`);
434
-        return;
435
-      }
436
-      
437
-      this.lastIsLocked = newIsLocked;
438
-      this.lastIsCompact = newIsCompact;
439
-      
440
-      // 更新滚动状态
441
-      this.isScrolled = newIsScrolled;
442
-      this.isLocked = newIsLocked;
443
-      this.isCompact = newIsCompact;
444
-      
445
-      console.log(`sticky-header: 容器滚动状态更新,scrollTop=${scrollTop}, isLocked=${this.isLocked}, isCompact=${this.isCompact}`);
446
-      
447
-      // 设置宽度匹配容器
448
-      if (this.isLocked) {
449
-        // 优先使用宽度目标元素,否则使用滚动容器
450
-        const widthTargetElement = this.getWidthTargetElement();
451
-        const targetElement = widthTargetElement || container;
452
-        const rect = targetElement.getBoundingClientRect();
453
-        this.headerWidth = rect.width;
454
-        this.headerLeft = rect.left;
455
-        console.log(`sticky-header: 容器滚动锁定,目标宽度: ${rect.width}px, 左侧位置: ${rect.left}px, 目标元素: ${widthTargetElement ? (this.widthTarget || '默认') : '滚动容器'}`);
456
-      } else {
457
-        this.headerWidth = null;
458
-        this.headerLeft = null;
459
-      }
460
-    });
461
-  }
462
-
463
-   private checkInitialScrollPosition(container: HTMLElement) {
464
-    const scrollTop = container.scrollTop || 0;
465
-    this.lastScrollTop = scrollTop;
466
-    
467
-    this.isScrolled = scrollTop > this.scrollThreshold;
468
-    this.isLocked = scrollTop > this.scrollThreshold;
469
-    this.isCompact = scrollTop > this.compactThreshold;
470
-    
471
-    // 记录初始状态
472
-    this.lastIsLocked = this.isLocked;
473
-    this.lastIsCompact = this.isCompact;
474
-    
475
-    if (this.isLocked) {
476
-      // 优先使用宽度目标元素,否则使用滚动容器
477
-      const widthTargetElement = this.getWidthTargetElement();
478
-      const targetElement = widthTargetElement || container;
479
-      const rect = targetElement.getBoundingClientRect();
480
-      this.headerWidth = rect.width;
481
-      this.headerLeft = rect.left;
482
-      console.log(`sticky-header: 初始容器滚动位置检查: scrollTop=${scrollTop}, isLocked=${this.isLocked}, isCompact=${this.isCompact}, 目标宽度: ${rect.width}px, 目标元素: ${widthTargetElement ? (this.widthTarget || '默认') : '滚动容器'}`);
483
-    } else {
484
-      this.headerWidth = null;
485
-      this.headerLeft = null;
486
-    }
487
-    
488
-    console.log(`sticky-header: 初始容器滚动位置检查完成: scrollTop=${scrollTop}, isLocked=${this.isLocked}, isCompact=${this.isCompact}, canScroll=${this.canScroll}`);
489
-  }
490
-
491
-  private cleanupScrollListener() {
492
-    if (this.scrollListener) {
493
-      this.scrollListener();
494
-      this.scrollListener = null;
495
-      console.log('sticky-header: 滚动监听器已清理');
496
-    }
497
-    this.isAutoDetecting = false;
498
-  }
499
-}

+ 1
- 1
src/app/pages/service-register-config/service-register-config.component.ts Parādīt failu

@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
3 3
 import { MatCard, MatCardContent } from '@angular/material/card';
4 4
 
5 5
 import { HttpErrorResponse } from '@angular/common/http';
6
-import { StickyHeaderComponent } from '../../components/sticky-header/sticky-header.component';
6
+import { StickyHeaderComponent } from 'base-core';
7 7
 import { ConfigMeta } from '../../models/config-meta.model';
8 8
 import { ConfigMetaService } from '../../services/config-meta.service';
9 9
 import { AgGridAngular } from 'ag-grid-angular';

+ 1
- 2
src/app/pages/tenant-list/tenant-list.component.ts Parādīt failu

@@ -10,8 +10,7 @@ import { MatProgressSpinner } from '@angular/material/progress-spinner';
10 10
 import { MatIcon } from '@angular/material/icon';
11 11
 import { TenantService } from '../../services/tenant.service';
12 12
 import { Tenant, TenantRequest } from '../../models/tenant.model';
13
-import { EnterNavigationDirective } from 'base-core';
14
-import { StickyHeaderComponent } from '../../components/sticky-header/sticky-header.component';
13
+import { EnterNavigationDirective, StickyHeaderComponent } from 'base-core';
15 14
 
16 15
 @Component({
17 16
   selector: 'app-tenant-list',

Notiek ielāde…
Atcelt
Saglabāt