a2bei4-utils 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -361,7 +361,111 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
361
361
  function getSearchParam(key) {
362
362
  const params = getAllSearchParams();
363
363
  return params[key];
364
- }
364
+ }
365
+
366
+ /**
367
+ * 全屏操作辅助工具对象
368
+ * @namespace fullscreenHelper
369
+ */
370
+ const fullscreenHelper = {
371
+ /**
372
+ * 请求进入全屏模式
373
+ * @param {Element} element - 要全屏显示的元素
374
+ * @returns {Promise<void> | undefined} 全屏请求 Promise(如支持)
375
+ */
376
+ requestFullscreen: (element) => {
377
+ if (!element) {
378
+ console.warn("未提供有效的 DOM 元素");
379
+ return;
380
+ }
381
+ if (element.requestFullscreen) {
382
+ return element.requestFullscreen();
383
+ } else if (element.mozRequestFullScreen) {
384
+ return element.mozRequestFullScreen();
385
+ } else if (element.webkitRequestFullscreen) {
386
+ return element.webkitRequestFullscreen();
387
+ } else if (element.msRequestFullscreen) {
388
+ return element.msRequestFullscreen();
389
+ } else {
390
+ console.warn("当前浏览器不支持全屏 API");
391
+ }
392
+ },
393
+
394
+ /**
395
+ * 退出全屏模式
396
+ * @returns {Promise<void> | undefined} 退出全屏请求 Promise(如支持)
397
+ */
398
+ exitFullscreen: () => {
399
+ if (document.exitFullscreen) {
400
+ return document.exitFullscreen();
401
+ } else if (document.mozCancelFullScreen) {
402
+ return document.mozCancelFullScreen();
403
+ } else if (document.webkitExitFullscreen) {
404
+ return document.webkitExitFullscreen();
405
+ } else if (document.msExitFullscreen) {
406
+ return document.msExitFullscreen();
407
+ }
408
+ },
409
+
410
+ /**
411
+ * 获取当前全屏元素
412
+ * @returns {Element | null} 当前处于全屏模式的元素,无则返回 null
413
+ */
414
+ getFullscreenElement: () => {
415
+ return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement || null;
416
+ },
417
+
418
+ /**
419
+ * 检测当前是否处于全屏模式
420
+ * @returns {boolean} 是否全屏中
421
+ */
422
+ isFullscreen: () => {
423
+ return !!(document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement);
424
+ },
425
+
426
+ /**
427
+ * 检测浏览器是否支持全屏 API
428
+ * @returns {boolean} 是否支持全屏
429
+ */
430
+ isFullscreenEnabled: () => {
431
+ return !!(document.fullscreenEnabled || document.mozFullScreenEnabled || document.webkitFullscreenEnabled || document.msFullscreenEnabled);
432
+ },
433
+
434
+ /**
435
+ * 切换指定元素的全屏状态
436
+ * @param {Element} element - 要切换全屏的元素
437
+ * @returns {Promise<void> | undefined} 全屏操作 Promise
438
+ */
439
+ toggleFullscreen: (element) => {
440
+ if (fullscreenHelper.isFullscreen()) {
441
+ return fullscreenHelper.exitFullscreen();
442
+ } else {
443
+ return fullscreenHelper.requestFullscreen(element);
444
+ }
445
+ },
446
+
447
+ /**
448
+ * 监听全屏变化事件
449
+ * @param {Function} callback - 全屏状态变化时的回调函数,参数为 isFullscreen: boolean
450
+ * @returns {Function} 取消监听的函数
451
+ */
452
+ onFullscreenChange: (callback) => {
453
+ const handler = () => {
454
+ callback(fullscreenHelper.isFullscreen());
455
+ };
456
+ document.addEventListener("fullscreenchange", handler);
457
+ document.addEventListener("webkitfullscreenchange", handler);
458
+ document.addEventListener("mozfullscreenchange", handler);
459
+ document.addEventListener("msfullscreenchange", handler);
460
+
461
+ return () => {
462
+ document.removeEventListener("fullscreenchange", handler);
463
+ document.removeEventListener("webkitfullscreenchange", handler);
464
+ document.removeEventListener("mozfullscreenchange", handler);
465
+ document.removeEventListener("msfullscreenchange", handler);
466
+ };
467
+ }
468
+ };
365
469
 
366
470
  //#region 数据类型判断
367
471
 
@@ -1906,6 +2010,64 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
1906
2010
  checked: [...checked],
1907
2011
  halfChecked: [...halfChecked]
1908
2012
  };
2013
+ }
2014
+
2015
+ /**
2016
+ * 在树形结构中查找目标节点的完整路径(从根节点到目标节点,含目标节点自身)。
2017
+ *
2018
+ * @template T extends Record<PropertyKey, any>
2019
+ * @param {T[]} nodes - 树形结构森林(支持多根)
2020
+ * @param {any} targetValue - 目标节点的 key 值
2021
+ * @param {string} [key='id'] - 节点唯一标识字段
2022
+ * @param {string} [parentKey='pid'] - 父节点标识字段(指向父节点的 key 值)
2023
+ * @param {string} [childrenKey='children'] - 子节点数组字段
2024
+ * @returns {T[]} 从根到目标节点的路径数组;未找到返回空数组
2025
+ *
2026
+ * @example
2027
+ * const tree = [
2028
+ * { id: 1, pid: null, children: [
2029
+ * { id: 2, pid: 1, children: [
2030
+ * { id: 3, pid: 2 }
2031
+ * ]}
2032
+ * ]}
2033
+ * ];
2034
+ * findTreeNodePath(tree, 3); // [{id:1, ...}, {id:2, ...}, {id:3, ...}]
2035
+ */
2036
+ function findTreeNodePath(nodes, targetValue, key = "id", parentKey = "pid", childrenKey = "children") {
2037
+ if (!Array.isArray(nodes) || nodes.length === 0 || targetValue == null) {
2038
+ return [];
2039
+ }
2040
+
2041
+ // 1. 建立节点索引
2042
+ const index = new Map();
2043
+ const stack = [...nodes];
2044
+
2045
+ while (stack.length) {
2046
+ const node = stack.pop();
2047
+ if (!node || typeof node !== "object") continue;
2048
+
2049
+ index.set(node[key], node);
2050
+
2051
+ const children = node[childrenKey];
2052
+ if (Array.isArray(children)) {
2053
+ stack.push(...children);
2054
+ }
2055
+ }
2056
+
2057
+ // 2. 回溯路径(防循环引用)
2058
+ const path = [];
2059
+ const visited = new Set();
2060
+ let cur = index.get(targetValue);
2061
+
2062
+ while (cur && !visited.has(cur[key])) {
2063
+ visited.add(cur[key]);
2064
+ path.push(cur);
2065
+
2066
+ const parentValue = cur[parentKey];
2067
+ cur = parentValue != null ? index.get(parentValue) : undefined;
2068
+ }
2069
+
2070
+ return path.reverse();
1909
2071
  }
1910
2072
 
1911
2073
  /**
@@ -2331,8 +2493,10 @@ registerProcessor('audio-stream-resampler-processor', AudioStreamResamplerProces
2331
2493
  exports.fetchOrDownloadByUrl = fetchOrDownloadByUrl;
2332
2494
  exports.findObjAttrValueById = findObjAttrValueById;
2333
2495
  exports.findTreeNodeById = findTreeNodeById;
2496
+ exports.findTreeNodePath = findTreeNodePath;
2334
2497
  exports.flatCompleteTree2NestedTree = flatCompleteTree2NestedTree;
2335
2498
  exports.formatTimeForLocale = formatTimeForLocale;
2499
+ exports.fullscreenHelper = fullscreenHelper;
2336
2500
  exports.getAllSearchParams = getAllSearchParams;
2337
2501
  exports.getDataType = getDataType;
2338
2502
  exports.getFunctionArgNames = getFunctionArgNames;