ZHIWEI666 commited on
Commit
786c475
·
verified ·
1 Parent(s): 06157f4

Upload 5 files

Browse files
前端页面/components/图片展示测试.js CHANGED
@@ -502,8 +502,6 @@ class CyberImageViewer {
502
  </svg>
503
  </button>
504
  <div class="cyber-keyboard-hint">
505
- <span><span class="cyber-key">←</span> ${escapeHtml(t('image.viewer.previous_short'))}</span>
506
- <span><span class="cyber-key">→</span> ${escapeHtml(t('image.viewer.next_short'))}</span>
507
  <span><span class="cyber-key">ESC</span> ${escapeHtml(t('image.viewer.close_short'))}</span>
508
  </div>
509
  </div>
@@ -623,6 +621,8 @@ class CyberImageViewer {
623
  pauseIcon.style.display = 'none';
624
  }
625
 
 
 
626
  // 触发状态变化回调
627
  this._autoPlayStateChangeCallbacks.forEach(cb => cb(this._autoPlayEnabled));
628
  }
@@ -762,6 +762,8 @@ class CyberImageViewer {
762
  _bindEvents() {
763
  // 键盘导航
764
  this._keydownHandler = (e) => {
 
 
765
  if (e.key === 'Tab') {
766
  const controls = [...this.container.querySelectorAll('button:not([disabled]), [tabindex="0"]')];
767
  if (!controls.length) { e.preventDefault(); this.container.focus(); return; }
@@ -775,22 +777,13 @@ class CyberImageViewer {
775
  return;
776
  }
777
  if (e.key === 'Escape') {
 
 
778
  this.close();
779
- } else if (e.key === 'ArrowLeft') {
780
- // 键盘导航使用屏幕中心作为波浪起点
781
- this._stopAutoPlay(); // 手动切换时停止自动播放
782
- this.prev(window.innerWidth / 2, window.innerHeight / 2);
783
- } else if (e.key === 'ArrowRight') {
784
- // 键盘导航使用屏幕中心作为波浪起点
785
- this._stopAutoPlay(); // 手动切换时停止自动播放
786
- this.next(window.innerWidth / 2, window.innerHeight / 2);
787
- } else if (e.key === ' ') {
788
- // 空格键切换自动播放状态
789
- e.preventDefault(); // 阻止页面滚动
790
- this.toggleAutoPlay();
791
  }
792
  };
793
- document.addEventListener('keydown', this._keydownHandler);
794
 
795
  // 点击导航区域 - 传递点击位置用于波浪效果
796
  this.elements.navLeft.addEventListener('click', (e) => {
@@ -1579,7 +1572,7 @@ class CyberImageViewer {
1579
  this._stopAutoPlay();
1580
 
1581
  // 清理事件监听
1582
- document.removeEventListener('keydown', this._keydownHandler);
1583
 
1584
  // 添加关闭动画
1585
  this.container.style.opacity = '1';
 
502
  </svg>
503
  </button>
504
  <div class="cyber-keyboard-hint">
 
 
505
  <span><span class="cyber-key">ESC</span> ${escapeHtml(t('image.viewer.close_short'))}</span>
506
  </div>
507
  </div>
 
621
  pauseIcon.style.display = 'none';
622
  }
623
 
624
+ btn.setAttribute('aria-label', btn.title);
625
+
626
  // 触发状态变化回调
627
  this._autoPlayStateChangeCallbacks.forEach(cb => cb(this._autoPlayEnabled));
628
  }
 
762
  _bindEvents() {
763
  // 键盘导航
764
  this._keydownHandler = (e) => {
765
+ if (e.defaultPrevented || e.isComposing || e.keyCode === 229
766
+ || e.ctrlKey || e.metaKey || e.altKey || (e.shiftKey && e.key !== 'Tab')) return;
767
  if (e.key === 'Tab') {
768
  const controls = [...this.container.querySelectorAll('button:not([disabled]), [tabindex="0"]')];
769
  if (!controls.length) { e.preventDefault(); this.container.focus(); return; }
 
777
  return;
778
  }
779
  if (e.key === 'Escape') {
780
+ e.preventDefault();
781
+ e.stopPropagation();
782
  this.close();
783
+
 
 
 
 
 
 
 
 
 
 
 
784
  }
785
  };
786
+ this.container.addEventListener('keydown', this._keydownHandler);
787
 
788
  // 点击导航区域 - 传递点击位置用于波浪效果
789
  this.elements.navLeft.addEventListener('click', (e) => {
 
1572
  this._stopAutoPlay();
1573
 
1574
  // 清理事件监听
1575
+ this.container.removeEventListener('keydown', this._keydownHandler);
1576
 
1577
  // 添加关闭动画
1578
  this.container.style.opacity = '1';
前端页面/components/图片沙盒组件.js CHANGED
@@ -314,28 +314,10 @@ export function setupImageSandboxEvents(detailView) {
314
  window.addEventListener('mouseup', handleMouseUp);
315
  viewport.addEventListener('mouseleave', () => { isDragging = false; viewport.style.cursor = 'grab'; });
316
 
317
- // ⌨️ 键盘左右切换
318
- const handleKeydown = (e) => {
319
- if (e.key === 'ArrowLeft' && imageUrls.length > 1) {
320
- loadImage(currentIndex > 0 ? currentIndex - 1 : imageUrls.length - 1);
321
- } else if (e.key === 'ArrowRight' && imageUrls.length > 1) {
322
- loadImage(currentIndex < imageUrls.length - 1 ? currentIndex + 1 : 0);
323
- }
324
- };
325
-
326
- // 当鼠标在视口内时启用键盘切换
327
- viewport.addEventListener('mouseenter', () => {
328
- document.addEventListener('keydown', handleKeydown);
329
- });
330
- viewport.addEventListener('mouseleave', () => {
331
- document.removeEventListener('keydown', handleKeydown);
332
- });
333
-
334
  // 🔧 P3优化:注册清理函数,供组件销毁时调用
335
  const cleanup = () => {
336
  window.removeEventListener('mousemove', handleMouseMove);
337
  window.removeEventListener('mouseup', handleMouseUp);
338
- document.removeEventListener('keydown', handleKeydown);
339
  };
340
  viewport._sandboxCleanup = cleanup;
341
  }
 
314
  window.addEventListener('mouseup', handleMouseUp);
315
  viewport.addEventListener('mouseleave', () => { isDragging = false; viewport.style.cursor = 'grab'; });
316
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  // 🔧 P3优化:注册清理函数,供组件销毁时调用
318
  const cleanup = () => {
319
  window.removeEventListener('mousemove', handleMouseMove);
320
  window.removeEventListener('mouseup', handleMouseUp);
 
321
  };
322
  viewport._sandboxCleanup = cleanup;
323
  }
前端页面/components/用户体验_国际化.js CHANGED
@@ -9,6 +9,7 @@
9
  // - 默认中文
10
 
11
  let currentLang = 'zh-CN';
 
12
 
13
  const translations = {
14
  'zh-CN': {
@@ -1259,8 +1260,8 @@ const translations = {
1259
  'image.viewer.close': '关闭 (ESC)',
1260
  'image.viewer.previous': '上一张 (←)',
1261
  'image.viewer.next': '下一张 (→)',
1262
- 'image.viewer.autoplay': '自动播放 (空格)',
1263
- 'image.viewer.pause': '暂停自动播放 (空格)',
1264
  'image.viewer.dialog': '图片查看器',
1265
  'image.viewer.previous_short': '上一张',
1266
  'image.viewer.next_short': '下一张',
@@ -3058,8 +3059,8 @@ const translations = {
3058
  'image.viewer.close': 'Close (Esc)',
3059
  'image.viewer.previous': 'Previous image (←)',
3060
  'image.viewer.next': 'Next image (→)',
3061
- 'image.viewer.autoplay': 'Start slideshow (Space)',
3062
- 'image.viewer.pause': 'Pause slideshow (Space)',
3063
  'image.viewer.dialog': 'Image viewer',
3064
  'image.viewer.previous_short': 'Previous',
3065
  'image.viewer.next_short': 'Next',
@@ -3434,9 +3435,13 @@ export function tIfExists(key, fallback = '') {
3434
  * @param {string} lang - 语言代码 ('zh-CN' | 'en-US')
3435
  */
3436
  export function setLanguage(lang) {
3437
- if (translations[lang]) {
3438
  currentLang = lang;
3439
- localStorage.setItem('comfy_ranking_lang', lang);
 
 
 
 
3440
 
3441
  // 触发语言变更事件
3442
  document.dispatchEvent(new CustomEvent('comfy-language-change', {
@@ -3457,18 +3462,24 @@ export function getLanguage() {
3457
  * 初始化 i18n
3458
  */
3459
  export function initI18n() {
 
 
 
 
3460
  // 🔧 修复:优先从全局设置读取语言
3461
  try {
3462
  const globalSettings = JSON.parse(localStorage.getItem('ComfyCommunity_Settings') || '{}');
3463
- if (globalSettings.language && translations[globalSettings.language]) {
3464
  currentLang = globalSettings.language;
3465
  return;
3466
  }
3467
  } catch (e) {}
3468
 
3469
  // 回退:从旧的独立存储读取
3470
- const savedLang = localStorage.getItem('comfy_ranking_lang');
3471
- if (savedLang && translations[savedLang]) {
 
 
3472
  currentLang = savedLang;
3473
  } else {
3474
  // 检测浏览器语言
 
9
  // - 默认中文
10
 
11
  let currentLang = 'zh-CN';
12
+ let pendingLanguage = null;
13
 
14
  const translations = {
15
  'zh-CN': {
 
1260
  'image.viewer.close': '关闭 (ESC)',
1261
  'image.viewer.previous': '上一张 (←)',
1262
  'image.viewer.next': '下一张 (→)',
1263
+ 'image.viewer.autoplay': '自动播放',
1264
+ 'image.viewer.pause': '暂停自动播放',
1265
  'image.viewer.dialog': '图片查看器',
1266
  'image.viewer.previous_short': '上一张',
1267
  'image.viewer.next_short': '下一张',
 
3059
  'image.viewer.close': 'Close (Esc)',
3060
  'image.viewer.previous': 'Previous image (←)',
3061
  'image.viewer.next': 'Next image (→)',
3062
+ 'image.viewer.autoplay': 'Start slideshow',
3063
+ 'image.viewer.pause': 'Pause slideshow',
3064
  'image.viewer.dialog': 'Image viewer',
3065
  'image.viewer.previous_short': 'Previous',
3066
  'image.viewer.next_short': 'Next',
 
3435
  * @param {string} lang - 语言代码 ('zh-CN' | 'en-US')
3436
  */
3437
  export function setLanguage(lang) {
3438
+ if (typeof lang === 'string' && Object.hasOwn(translations, lang)) {
3439
  currentLang = lang;
3440
+ pendingLanguage = lang;
3441
+ try {
3442
+ localStorage.setItem('comfy_ranking_lang', lang);
3443
+ pendingLanguage = null;
3444
+ } catch {}
3445
 
3446
  // 触发语言变更事件
3447
  document.dispatchEvent(new CustomEvent('comfy-language-change', {
 
3462
  * 初始化 i18n
3463
  */
3464
  export function initI18n() {
3465
+ if (pendingLanguage !== null) {
3466
+ currentLang = pendingLanguage;
3467
+ return;
3468
+ }
3469
  // 🔧 修复:优先从全局设置读取语言
3470
  try {
3471
  const globalSettings = JSON.parse(localStorage.getItem('ComfyCommunity_Settings') || '{}');
3472
+ if (typeof globalSettings.language === 'string' && Object.hasOwn(translations, globalSettings.language)) {
3473
  currentLang = globalSettings.language;
3474
  return;
3475
  }
3476
  } catch (e) {}
3477
 
3478
  // 回退:从旧的独立存储读取
3479
+ let savedLang = null;
3480
+ try { savedLang = localStorage.getItem('comfy_ranking_lang'); }
3481
+ catch {}
3482
+ if (typeof savedLang === 'string' && Object.hasOwn(translations, savedLang)) {
3483
  currentLang = savedLang;
3484
  } else {
3485
  // 检测浏览器语言
前端页面/components/用户体验增强.js CHANGED
@@ -218,118 +218,48 @@ export function createAutoSaver(formId, formElement, options = {}) {
218
  // ==========================================
219
  // ⌨️ P2-3: 快捷键支持
220
  // ==========================================
221
- // 特点:
222
- // - Esc 关闭弹窗
223
- // - Enter 确认提交
224
- // - Ctrl+S 保存
225
- // - 可配置扩展
226
-
227
  const keyboardShortcuts = new Map();
228
- let shortcutsInitialized = false;
229
 
230
- /**
231
- * 注册全局快捷键
232
- * @param {string} key - 按键组合 (如 'Escape', 'Enter', 'Ctrl+S')
233
- * @param {Function} handler - 处理函数
234
- * @param {Object} options - 配置选项
235
- */
236
  export function registerShortcut(key, handler, options = {}) {
237
- const {
238
- scope = 'global', // 作用域
239
- preventDefault = true, // 是否阻止默认行为
240
- description = '' // 描述
241
- } = options;
242
-
243
- if (!keyboardShortcuts.has(key)) {
244
- keyboardShortcuts.set(key, []);
245
- }
246
-
247
- keyboardShortcuts.get(key).push({
248
- handler,
249
- scope,
250
- preventDefault,
251
- description
252
- });
 
 
 
 
 
 
 
 
 
253
  }
254
 
255
- /**
256
- * 移除快捷键
257
- * @param {string} key - 按键组合
258
- * @param {Function} handler - 处理函数(可选,不传则移除所有)
259
- */
260
  export function unregisterShortcut(key, handler = null) {
261
- if (handler && keyboardShortcuts.has(key)) {
262
- const handlers = keyboardShortcuts.get(key);
263
- const filtered = handlers.filter(h => h.handler !== handler);
264
- if (filtered.length > 0) {
265
- keyboardShortcuts.set(key, filtered);
266
- } else {
267
- keyboardShortcuts.delete(key);
268
- }
269
- } else {
270
- keyboardShortcuts.delete(key);
271
  }
 
 
272
  }
273
 
274
- /**
275
- * 初始化快捷键系统
276
- */
277
- export function initKeyboardShortcuts() {
278
- if (shortcutsInitialized) return;
279
- shortcutsInitialized = true;
280
-
281
- document.addEventListener('keydown', (e) => {
282
- // 构建按键标识
283
- let keyCombo = '';
284
- if (e.ctrlKey || e.metaKey) keyCombo += 'Ctrl+';
285
- if (e.altKey) keyCombo += 'Alt+';
286
- if (e.shiftKey) keyCombo += 'Shift+';
287
- keyCombo += e.key;
288
-
289
- // 也检查单独的按键
290
- const keysToCheck = [keyCombo];
291
- if (!e.ctrlKey && !e.altKey && !e.shiftKey) {
292
- keysToCheck.push(e.key);
293
- }
294
-
295
- for (const key of keysToCheck) {
296
- if (keyboardShortcuts.has(key)) {
297
- const handlers = keyboardShortcuts.get(key);
298
- for (const { handler, preventDefault } of handlers) {
299
- // 跳过在输入框中的快捷键(除了 Escape)
300
- const isInput = ['INPUT', 'TEXTAREA', 'SELECT'].includes(document.activeElement?.tagName);
301
- if (isInput && key !== 'Escape') continue;
302
-
303
- if (preventDefault) {
304
- e.preventDefault();
305
- }
306
- handler(e);
307
- return;
308
- }
309
- }
310
- }
311
- });
312
-
313
- // 注册默认快捷键
314
- _registerDefaultShortcuts();
315
- }
316
-
317
- function _registerDefaultShortcuts() {
318
- // Esc 关闭最上层弹窗
319
- registerShortcut('Escape', () => {
320
- const modals = document.querySelectorAll('[data-modal="true"]');
321
- if (modals.length > 0) {
322
- const topModal = modals[modals.length - 1];
323
- const closeBtn = topModal.querySelector('[data-close]');
324
- if (closeBtn) closeBtn.click();
325
- }
326
- }, { description: '关闭弹窗' });
327
-
328
- // Ctrl+S 保存(触发自定义事件)
329
- registerShortcut('Ctrl+s', () => {
330
- document.dispatchEvent(new CustomEvent('comfy-save-shortcut'));
331
- }, { description: '保存' });
332
- }
333
 
334
 
335
  // ==========================================
@@ -574,9 +504,6 @@ export function initUXEnhancements() {
574
  // 应用安全区域
575
  applySafeAreaInsets();
576
 
577
- // 初始化快捷键
578
- initKeyboardShortcuts();
579
-
580
  // 初始化 i18n
581
  initI18n();
582
 
 
218
  // ==========================================
219
  // ⌨️ P2-3: 快捷键支持
220
  // ==========================================
 
 
 
 
 
 
221
  const keyboardShortcuts = new Map();
 
222
 
223
+ /** 仅为明确的局部容器注册按键;不接受页面全局作用域。 */
 
 
 
 
 
224
  export function registerShortcut(key, handler, options = {}) {
225
+ const { scope, preventDefault = true } = options;
226
+ if (!scope || scope.nodeType !== 1 || scope === document.body || scope === document.documentElement
227
+ || typeof handler !== 'function' || typeof key !== 'string') return () => {};
228
+ const listener = event => {
229
+ if (!scope.isConnected || !scope.contains(event.target) || event.defaultPrevented
230
+ || event.isComposing || event.keyCode === 229 || event.repeat) return;
231
+ if (event.target.closest('input, textarea, select, [contenteditable]:not([contenteditable="false"])')
232
+ && event.key !== 'Escape') return;
233
+ const combo = `${event.ctrlKey || event.metaKey ? 'Ctrl+' : ''}${event.altKey ? 'Alt+' : ''}${event.shiftKey ? 'Shift+' : ''}${event.key}`;
234
+ if (combo !== key) return;
235
+ if (preventDefault) event.preventDefault();
236
+ event.stopPropagation();
237
+ handler(event);
238
+ };
239
+ const entry = { handler, scope, listener };
240
+ const entries = keyboardShortcuts.get(key) || [];
241
+ entries.push(entry);
242
+ keyboardShortcuts.set(key, entries);
243
+ scope.addEventListener('keydown', listener);
244
+ return () => {
245
+ scope.removeEventListener('keydown', listener);
246
+ const remaining = (keyboardShortcuts.get(key) || []).filter(item => item !== entry);
247
+ if (remaining.length) keyboardShortcuts.set(key, remaining);
248
+ else keyboardShortcuts.delete(key);
249
+ };
250
  }
251
 
 
 
 
 
 
252
  export function unregisterShortcut(key, handler = null) {
253
+ const remaining = [];
254
+ for (const entry of keyboardShortcuts.get(key) || []) {
255
+ if (handler && entry.handler !== handler) remaining.push(entry);
256
+ else entry.scope.removeEventListener('keydown', entry.listener);
 
 
 
 
 
 
257
  }
258
+ if (remaining.length) keyboardShortcuts.set(key, remaining);
259
+ else keyboardShortcuts.delete(key);
260
  }
261
 
262
+ export function initKeyboardShortcuts() {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
 
264
 
265
  // ==========================================
 
504
  // 应用安全区域
505
  applySafeAreaInsets();
506
 
 
 
 
507
  // 初始化 i18n
508
  initI18n();
509
 
前端页面/components/视频播放器组件.js CHANGED
@@ -2,7 +2,7 @@
2
  // ==========================================
3
  // 🎬 自定义视频播放器组件
4
  // ==========================================
5
- // 功能:内嵌视频播放 + 全屏沉浸式播放,支持自定义控制栏、键盘快捷键
6
  // 接口:getVideoPlayerHTML / setupVideoPlayerEvents / cleanupVideoPlayer / openFullscreenVideo
7
  // ==========================================
8
 
@@ -676,56 +676,6 @@ export function setupVideoPlayerEvents(container) {
676
  });
677
  }
678
 
679
- // 8. 键盘快捷键
680
- const handleKeydown = (e) => {
681
- if (document.activeElement !== player) return;
682
- switch (e.key) {
683
- case ' ':
684
- case 'k':
685
- e.preventDefault();
686
- togglePlay();
687
- break;
688
- case 'ArrowLeft':
689
- e.preventDefault();
690
- video.currentTime = Math.max(0, video.currentTime - 5);
691
- break;
692
- case 'ArrowRight':
693
- e.preventDefault();
694
- video.currentTime = Math.min(video.duration || 0, video.currentTime + 5);
695
- break;
696
- case 'ArrowUp':
697
- e.preventDefault();
698
- video.volume = Math.min(1, video.volume + 0.1);
699
- if (video.volume > 0) video.muted = false;
700
- if (volumeSlider) volumeSlider.value = Math.round(video.volume * 100);
701
- updateVolumeIcon();
702
- break;
703
- case 'ArrowDown':
704
- e.preventDefault();
705
- video.volume = Math.max(0, video.volume - 0.1);
706
- if (volumeSlider) volumeSlider.value = Math.round(video.volume * 100);
707
- updateVolumeIcon();
708
- break;
709
- case 'f':
710
- case 'F':
711
- e.preventDefault();
712
- if (btnFullscreen) btnFullscreen.click();
713
- break;
714
- case 'm':
715
- case 'M':
716
- e.preventDefault();
717
- video.muted = !video.muted;
718
- updateVolumeIcon();
719
- break;
720
- }
721
- };
722
- player.addEventListener('keydown', handleKeydown);
723
-
724
- // 点击播放器获取焦点
725
- player.addEventListener('click', () => {
726
- player.focus();
727
- });
728
-
729
  // 9. 控制栏自动隐藏
730
  player.addEventListener('mousemove', resetHideTimer);
731
  player.addEventListener('mouseenter', resetHideTimer);
@@ -897,7 +847,7 @@ export function openFullscreenVideo(videoUrl, posterUrl, options = {}) {
897
  if (destroyed) return;
898
  destroyed = true;
899
  if (hideControlsTimer) clearTimeout(hideControlsTimer);
900
- document.removeEventListener('keydown', handleKeydown);
901
  document.removeEventListener('click', handleDocClickForSpeed);
902
  window.removeEventListener('mousemove', handleMouseMove);
903
  window.removeEventListener('mouseup', handleMouseUp);
@@ -1100,53 +1050,16 @@ export function openFullscreenVideo(videoUrl, posterUrl, options = {}) {
1100
  // 关闭按钮
1101
  closeBtn.addEventListener('click', () => destroy(video.currentTime));
1102
 
1103
- // 键盘快捷键
1104
- const handleKeydown = (e) => {
1105
- switch (e.key) {
1106
- case 'Escape':
1107
- e.preventDefault();
1108
- destroy(video.currentTime);
1109
- break;
1110
- case ' ':
1111
- case 'k':
1112
- e.preventDefault();
1113
- togglePlay();
1114
- break;
1115
- case 'ArrowLeft':
1116
- e.preventDefault();
1117
- video.currentTime = Math.max(0, video.currentTime - 5);
1118
- break;
1119
- case 'ArrowRight':
1120
- e.preventDefault();
1121
- video.currentTime = Math.min(video.duration || 0, video.currentTime + 5);
1122
- break;
1123
- case 'ArrowUp':
1124
- e.preventDefault();
1125
- video.volume = Math.min(1, video.volume + 0.1);
1126
- if (video.volume > 0) video.muted = false;
1127
- volumeSlider.value = Math.round(video.volume * 100);
1128
- updateVolumeIcon();
1129
- break;
1130
- case 'ArrowDown':
1131
- e.preventDefault();
1132
- video.volume = Math.max(0, video.volume - 0.1);
1133
- volumeSlider.value = Math.round(video.volume * 100);
1134
- updateVolumeIcon();
1135
- break;
1136
- case 'f':
1137
- case 'F':
1138
- e.preventDefault();
1139
- destroy(video.currentTime);
1140
- break;
1141
- case 'm':
1142
- case 'M':
1143
- e.preventDefault();
1144
- video.muted = !video.muted;
1145
- updateVolumeIcon();
1146
- break;
1147
- }
1148
  };
1149
- document.addEventListener('keydown', handleKeydown);
 
1150
 
1151
  // 控制栏自动隐藏
1152
  overlay.addEventListener('mousemove', resetHideTimer);
 
2
  // ==========================================
3
  // 🎬 自定义视频播放器组件
4
  // ==========================================
5
+ // 功能:内嵌视频播放 + 全屏沉浸式播放,支持自定义控制栏
6
  // 接口:getVideoPlayerHTML / setupVideoPlayerEvents / cleanupVideoPlayer / openFullscreenVideo
7
  // ==========================================
8
 
 
676
  });
677
  }
678
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
679
  // 9. 控制栏自动隐藏
680
  player.addEventListener('mousemove', resetHideTimer);
681
  player.addEventListener('mouseenter', resetHideTimer);
 
847
  if (destroyed) return;
848
  destroyed = true;
849
  if (hideControlsTimer) clearTimeout(hideControlsTimer);
850
+ overlay.removeEventListener('keydown', handleKeydown);
851
  document.removeEventListener('click', handleDocClickForSpeed);
852
  window.removeEventListener('mousemove', handleMouseMove);
853
  window.removeEventListener('mouseup', handleMouseUp);
 
1050
  // 关闭按钮
1051
  closeBtn.addEventListener('click', () => destroy(video.currentTime));
1052
 
1053
+ const handleKeydown = event => {
1054
+ if (event.defaultPrevented || event.isComposing || event.keyCode === 229
1055
+ || event.ctrlKey || event.metaKey || event.altKey || event.shiftKey
1056
+ || event.key !== 'Escape') return;
1057
+ event.preventDefault();
1058
+ event.stopPropagation();
1059
+ destroy(video.currentTime);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1060
  };
1061
+ overlay.addEventListener('keydown', handleKeydown);
1062
+ closeBtn.focus();
1063
 
1064
  // 控制栏自动隐藏
1065
  overlay.addEventListener('mousemove', resetHideTimer);