path.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // 路径导航模块(面包屑导航)
  2. class PathNavigator {
  3. constructor(options) {
  4. // 面包屑容器元素
  5. this.container = options.container;
  6. // 根目录名称
  7. this.rootName = options.rootName || '全部文件';
  8. // 当前路径
  9. this.currentPath = '';
  10. // 路径变化回调
  11. this.onNavigate = options.onNavigate || null;
  12. this.init();
  13. }
  14. init() {
  15. this.bindEvents();
  16. this.render();
  17. }
  18. bindEvents() {
  19. // 面包屑点击事件
  20. this.container.addEventListener('click', (e) => {
  21. if (e.target.classList.contains('breadcrumb-item')) {
  22. const path = e.target.dataset.path;
  23. this.navigateTo(path);
  24. }
  25. });
  26. }
  27. // 导航到指定路径
  28. navigateTo(path) {
  29. if (this.currentPath === path) return;
  30. this.currentPath = path;
  31. this.render();
  32. // 触发回调
  33. if (this.onNavigate) {
  34. this.onNavigate(path);
  35. }
  36. }
  37. // 获取当前路径
  38. getPath() {
  39. return this.currentPath;
  40. }
  41. // 设置路径(不触发回调,仅更新显示)
  42. setPath(path) {
  43. this.currentPath = path;
  44. this.render();
  45. }
  46. // 渲染面包屑
  47. render() {
  48. this.container.innerHTML = '';
  49. // 添加根目录
  50. const rootItem = document.createElement('span');
  51. rootItem.className = 'breadcrumb-item';
  52. rootItem.textContent = this.rootName;
  53. rootItem.dataset.path = '';
  54. if (this.currentPath === '') {
  55. rootItem.classList.add('active');
  56. }
  57. this.container.appendChild(rootItem);
  58. // 添加路径中的各个部分
  59. if (this.currentPath) {
  60. const parts = this.currentPath.split('/').filter(p => p);
  61. let accumulatedPath = '';
  62. parts.forEach((part, index) => {
  63. accumulatedPath += part;
  64. const item = document.createElement('span');
  65. item.className = 'breadcrumb-item';
  66. item.textContent = part;
  67. item.dataset.path = accumulatedPath;
  68. if (index === parts.length - 1) {
  69. item.classList.add('active');
  70. }
  71. this.container.appendChild(item);
  72. if (index < parts.length - 1) {
  73. accumulatedPath += '/';
  74. }
  75. });
  76. }
  77. }
  78. // 返回上一级
  79. goUp() {
  80. if (!this.currentPath) return;
  81. const parts = this.currentPath.split('/').filter(p => p);
  82. parts.pop();
  83. const parentPath = parts.join('/');
  84. this.navigateTo(parentPath);
  85. }
  86. // 进入子目录
  87. goInto(folderName) {
  88. const newPath = this.currentPath
  89. ? `${this.currentPath}/${folderName}`
  90. : folderName;
  91. this.navigateTo(newPath);
  92. }
  93. // 回到根目录
  94. goRoot() {
  95. this.navigateTo('');
  96. }
  97. // 获取当前目录名
  98. getCurrentFolderName() {
  99. if (!this.currentPath) return this.rootName;
  100. const parts = this.currentPath.split('/').filter(p => p);
  101. return parts[parts.length - 1] || this.rootName;
  102. }
  103. // 获取父目录路径
  104. getParentPath() {
  105. if (!this.currentPath) return '';
  106. const parts = this.currentPath.split('/').filter(p => p);
  107. parts.pop();
  108. return parts.join('/');
  109. }
  110. // 判断是否在根目录
  111. isAtRoot() {
  112. return this.currentPath === '';
  113. }
  114. }