dashboard-shell-shell 1.0.1000000116 → 1.0.1000000117

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.
Files changed (124) hide show
  1. package/assets/images/action.svg +6 -0
  2. package/assets/images/pl/logo.png +0 -0
  3. package/assets/styles/base/_functions.scss +0 -0
  4. package/assets/styles/base/_mixins.scss +1 -1
  5. package/assets/styles/global/_button.scss +17 -10
  6. package/assets/styles/global/_form.scss +2 -2
  7. package/assets/styles/global/_labeled-input.scss +6 -2
  8. package/assets/styles/global/_select.scss +6 -7
  9. package/assets/styles/global/_table.scss +3 -2
  10. package/assets/styles/global/_tooltip.scss +8 -1
  11. package/assets/styles/themes/_dark.scss +2 -0
  12. package/assets/styles/themes/_light.scss +5 -2
  13. package/assets/styles/vendor/vue-select.scss +2 -1
  14. package/assets/translations/en-us.yaml +1 -3
  15. package/assets/translations/zh-hans.yaml +51 -28
  16. package/components/ActionDropdown.vue +1 -0
  17. package/components/ActionMenuShell.vue +6 -3
  18. package/components/BrandImage.vue +22 -0
  19. package/components/ClusterIconMenu.vue +1 -1
  20. package/components/CodeMirror.vue +1 -0
  21. package/components/CruResource.vue +1 -1
  22. package/components/CruResourceFooter.vue +1 -1
  23. package/components/ExplorerProjectsNamespaces.vue +4 -24
  24. package/components/GlobalRoleBindings.vue +112 -48
  25. package/components/IndentedPanel.vue +4 -10
  26. package/components/PromptRemove.vue +3 -3
  27. package/components/ResourceDetail/Masthead.vue +190 -242
  28. package/components/ResourceDetail/index.vue +20 -5
  29. package/components/ResourceList/Masthead.vue +146 -84
  30. package/components/ResourceList/ResourceLoadingIndicator.vue +5 -2
  31. package/components/ResourceTable.vue +76 -1
  32. package/components/SideNav.vue +66 -29
  33. package/components/SortableTable/THead.vue +6 -0
  34. package/components/SortableTable/index.vue +481 -388
  35. package/components/Tabbed/index.vue +4 -5
  36. package/components/auth/Principal.vue +3 -2
  37. package/components/auth/RoleDetailEdit.vue +58 -5
  38. package/components/auth/SelectPrincipal.vue +1 -0
  39. package/components/form/BannerSettings.vue +18 -16
  40. package/components/form/ChangePassword.vue +4 -4
  41. package/components/form/ColorInput.vue +32 -8
  42. package/components/form/Footer.vue +1 -1
  43. package/components/form/InputWithSelect.vue +2 -0
  44. package/components/form/KeyValue.vue +31 -7
  45. package/components/form/LabeledSelect.vue +178 -178
  46. package/components/form/Members/ClusterPermissionsEditor.vue +1 -2
  47. package/components/form/Members/MembershipEditor.vue +1 -1
  48. package/components/form/NameNsDescription.vue +24 -11
  49. package/components/form/Password.vue +6 -2
  50. package/components/form/ResourceQuota/Namespace.vue +1 -1
  51. package/components/form/ResourceQuota/NamespaceRow.vue +13 -10
  52. package/components/form/ResourceQuota/ProjectRow.vue +0 -1
  53. package/components/form/Select.vue +2 -2
  54. package/components/nav/Favorite.vue +5 -1
  55. package/components/nav/Group.vue +69 -23
  56. package/components/nav/Header.vue +82 -17
  57. package/components/nav/HeaderPageActionMenu.vue +1 -0
  58. package/components/nav/NamespaceFilter.vue +0 -3
  59. package/components/nav/TopLevelMenu.vue +182 -119
  60. package/components/nav/Type.vue +48 -11
  61. package/composables/useClickOutside.ts +1 -1
  62. package/config/product/auth.js +16 -7
  63. package/config/product/explorer.js +1 -1
  64. package/config/product/settings.js +17 -8
  65. package/config/settings.ts +28 -0
  66. package/edit/management.cattle.io.user.vue +17 -4
  67. package/edit/networking.k8s.io.ingress/RulePath.vue +1 -1
  68. package/edit/token.vue +1 -1
  69. package/list/harvesterhci.io.management.cluster.vue +17 -0
  70. package/list/management.cattle.io.setting.vue +22 -13
  71. package/list/management.cattle.io.user.vue +25 -14
  72. package/list/provisioning.cattle.io.cluster.vue +6 -7
  73. package/mixins/brand.js +17 -0
  74. package/package.json +1 -1
  75. package/pages/auth/login.vue +84 -29
  76. package/pages/c/_cluster/auth/roles/index.vue +61 -14
  77. package/pages/c/_cluster/settings/banners.vue +174 -101
  78. package/pages/c/_cluster/settings/brand.vue +348 -301
  79. package/pages/c/_cluster/settings/performance.vue +61 -38
  80. package/pages/home.vue +70 -21
  81. package/pages/prefs.vue +25 -23
  82. package/pkg/tsconfig.json +9 -9
  83. package/pkg/vue.config.js +1 -1
  84. package/promptRemove/mixin/roleDeletionCheck.js +2 -2
  85. package/scripts/clean +0 -0
  86. package/scripts/extension/bundle +0 -0
  87. package/scripts/extension/helm/scripts/package +0 -0
  88. package/scripts/extension/helm/scripts/patch +0 -0
  89. package/scripts/extension/helm/scripts/version +0 -0
  90. package/scripts/extension/helmpatch +0 -0
  91. package/scripts/extension/parse-tag-name +0 -0
  92. package/scripts/extension/publish +0 -0
  93. package/scripts/publish-shell.sh +86 -60
  94. package/scripts/serve-pkgs +0 -0
  95. package/scripts/sync-shell-deps +0 -0
  96. package/scripts/typegen.sh +44 -28
  97. package/store/i18n.js +5 -5
  98. package/store/prefs.js +17 -5
  99. package/store/type-map.js +2 -1
  100. package/types/shell/index.d.ts +1 -1
  101. package/utils/error.js +4 -0
  102. package/utils/router.js +3 -3
  103. package/vue.config.js +1 -6
  104. package/components/rancherResourceDetail/Masthead.vue +0 -769
  105. package/components/rancherResourceDetail/__tests__/Masthead.test.ts +0 -65
  106. package/components/rancherResourceDetail/index.vue +0 -591
  107. package/components/rancherResourceList/Masthead.vue +0 -375
  108. package/components/rancherResourceList/ResourceLoadingIndicator.vue +0 -140
  109. package/components/rancherResourceList/index.vue +0 -307
  110. package/components/rancherResourceList/resource-list.config.js +0 -7
  111. package/components/rancherResourceTable.vue +0 -783
  112. package/components/rancherSortableTable/THead.vue +0 -561
  113. package/components/rancherSortableTable/actions.js +0 -153
  114. package/components/rancherSortableTable/advanced-filtering.js +0 -272
  115. package/components/rancherSortableTable/debug.js +0 -117
  116. package/components/rancherSortableTable/filtering.js +0 -290
  117. package/components/rancherSortableTable/grouping.js +0 -48
  118. package/components/rancherSortableTable/index.vue +0 -2712
  119. package/components/rancherSortableTable/paging.js +0 -155
  120. package/components/rancherSortableTable/selection.js +0 -629
  121. package/components/rancherSortableTable/sortable-config.ts +0 -4
  122. package/components/rancherSortableTable/sorting.js +0 -129
  123. package/types/cloud-shell/index.d.ts +0 -11014
  124. /package/components/{rancherResourceList → ResourceList}/Masthead-btn.vue +0 -0
@@ -52,7 +52,10 @@ export default {
52
52
  helper.update(args);
53
53
  }
54
54
 
55
+ const topLevelPermissions = sessionStorage.getItem('TOPLEVELPERMISSIONS') || ''
56
+
55
57
  return {
58
+ topLevelPermissions,
56
59
  shown: false,
57
60
  displayVersion,
58
61
  fullVersion,
@@ -460,12 +463,14 @@ export default {
460
463
 
461
464
  <template>
462
465
  <div>
463
- <!-- Overlay -->
466
+ <!-- ====================== 遮罩层(点击可关闭菜单) ====================== -->
464
467
  <div
465
468
  v-if="shown"
466
469
  class="side-menu-glass"
467
470
  @click="hide()"
468
471
  />
472
+
473
+ <!-- ====================== 菜单主容器(带淡入淡出过渡) ====================== -->
469
474
  <transition name="fade">
470
475
  <!-- Side menu -->
471
476
  <div
@@ -476,8 +481,11 @@ export default {
476
481
  role="navigation"
477
482
  :aria-label="t('nav.ariaLabel.topLevelMenu')"
478
483
  >
479
- <!-- Logo and name -->
484
+
485
+ <!-- ====================== 菜单头部(Logo + 菜单按钮) ====================== -->
480
486
  <div class="title">
487
+
488
+ <!-- 菜单按钮(汉堡图标) -->
481
489
  <div
482
490
  data-testid="top-level-menu"
483
491
  :aria-label="t('nav.expandCollapseAppBar')"
@@ -488,6 +496,8 @@ export default {
488
496
  @keyup.space="toggle()"
489
497
  @click="toggle()"
490
498
  >
499
+
500
+ <!-- 汉堡菜单SVG图标 -->
491
501
  <svg
492
502
  class="menu-icon"
493
503
  xmlns="http://www.w3.org/2000/svg"
@@ -500,19 +510,22 @@ export default {
500
510
  fill="none"
501
511
  /><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" /></svg>
502
512
  </div>
503
- <div class="side-menu-logo">
513
+
514
+ <!-- 品牌Logo -->
515
+ <div v-if="topLevelPermissions && topLevelPermissions === 'superadmin'" class="side-menu-logo">
504
516
  <BrandImage
505
517
  data-testid="side-menu__brand-img"
506
518
  :alt="t('nav.alt.mainMenuRancherLogo')"
507
- file-name="rancher-logo.svg"
519
+ file-name="logo.png"
508
520
  />
509
521
  </div>
510
522
  </div>
511
523
 
512
- <!-- Menu body -->
524
+ <!-- ====================== 菜单内容区 ====================== -->
513
525
  <div class="body">
514
- <div>
515
- <!-- Home button -->
526
+ <div v-if="topLevelPermissions && topLevelPermissions === 'superadmin'">
527
+
528
+ <!-- 首页按钮 -->
516
529
  <div @click="hide()">
517
530
  <router-link
518
531
  class="option cluster selector home"
@@ -520,6 +533,8 @@ export default {
520
533
  role="link"
521
534
  :aria-label="t('nav.ariaLabel.homePage')"
522
535
  >
536
+
537
+ <!-- 首页图标 -->
523
538
  <svg
524
539
  v-clean-tooltip="getTooltipConfig(t('nav.home'))"
525
540
  class="top-menu-icon"
@@ -536,12 +551,14 @@ export default {
536
551
  </div>
537
552
  </router-link>
538
553
  </div>
539
- <!-- Search bar -->
554
+
555
+ <!-- 集群搜索框 -->
540
556
  <div
541
557
  v-if="showClusterSearch"
542
558
  class="clusters-search"
543
559
  >
544
560
  <div class="clusters-search-count">
561
+ <!-- 当前搜索到的集群数量 -->
545
562
  <span>{{ clusterFilterCount }}</span>
546
563
  {{ t('nav.search.clusters') }}
547
564
  <i
@@ -560,10 +577,14 @@ export default {
560
577
  :tabindex="!shown ? -1 : 0"
561
578
  :aria-label="t('nav.search.ariaLabel')"
562
579
  >
580
+
581
+ <!-- 搜索图标 -->
563
582
  <i
564
583
  class="magnifier icon icon-search"
565
584
  :class="{ active: clusterFilter }"
566
585
  />
586
+
587
+ <!-- 清空按钮 -->
567
588
  <i
568
589
  v-if="clusterFilter"
569
590
  class="icon icon-close"
@@ -573,9 +594,11 @@ export default {
573
594
  </div>
574
595
  </div>
575
596
 
576
- <!-- Harvester extras -->
597
+ <!-- ====================== Harvester 相关功能区 ====================== -->
577
598
  <template v-if="hciApps.length">
578
599
  <div class="category" />
600
+
601
+ <!-- 跳转 Harvester Dashboard -->
579
602
  <div>
580
603
  <a
581
604
  v-if="isRancherInHarvester"
@@ -591,6 +614,8 @@ export default {
591
614
  </div>
592
615
  </a>
593
616
  </div>
617
+
618
+ <!-- Harvester 应用列表 -->
594
619
  <div
595
620
  v-for="(a, i) in appBar.hciApps"
596
621
  :key="i"
@@ -613,14 +638,14 @@ export default {
613
638
  </div>
614
639
  </template>
615
640
 
616
- <!-- Cluster menu -->
617
- <template v-if="!!allClustersCount">
641
+ <!-- ====================== 集群列表 ====================== -->
642
+ <template v-if="topLevelPermissions && topLevelPermissions === 'superadmin' && !!allClustersCount">
618
643
  <div
619
644
  ref="clusterList"
620
645
  class="clusters"
621
646
  :style="pinnedClustersHeight"
622
647
  >
623
- <!-- Pinned Clusters -->
648
+ <!-- 已固定集群 -->
624
649
  <div
625
650
  v-if="showPinClusters && pinFiltered.length"
626
651
  class="clustersPinned"
@@ -631,11 +656,13 @@ export default {
631
656
  :data-testid="`pinned-ready-cluster-${index}`"
632
657
  @click="hide()"
633
658
  >
634
- <button
659
+
660
+ <!-- 可用集群按钮 -->
661
+ <span
635
662
  v-if="c.ready"
636
663
  v-shortkey.push="{windows: ['alt'], mac: ['option']}"
637
664
  :data-testid="`pinned-menu-cluster-${ c.id }`"
638
- class="cluster selector option"
665
+ class="clusterBtn cluster selector option"
639
666
  :class="{'active-menu-link': c.isMenuActive }"
640
667
  :to="c.clusterRoute"
641
668
  role="button"
@@ -665,7 +692,9 @@ export default {
665
692
  :cluster="c"
666
693
  :tab-order="shown ? 0 : -1"
667
694
  />
668
- </button>
695
+ </span>
696
+
697
+ <!-- 不可用集群 -->
669
698
  <span
670
699
  v-else
671
700
  class="option cluster selector disabled"
@@ -694,6 +723,8 @@ export default {
694
723
  />
695
724
  </span>
696
725
  </div>
726
+
727
+ <!-- 分割线 -->
697
728
  <div
698
729
  v-if="clustersFiltered.length > 0"
699
730
  class="category-title"
@@ -702,7 +733,7 @@ export default {
702
733
  </div>
703
734
  </div>
704
735
 
705
- <!-- Clusters Search result -->
736
+ <!-- 搜索结果集群列表 -->
706
737
  <div class="clustersList">
707
738
  <div
708
739
  v-for="(c, index) in appBar.clustersFiltered"
@@ -710,11 +741,13 @@ export default {
710
741
  :data-testid="`top-level-menu-cluster-${index}`"
711
742
  @click="hide()"
712
743
  >
713
- <button
744
+
745
+ <!-- 可用集群 -->
746
+ <span
714
747
  v-if="c.ready"
715
748
  v-shortkey.push="{windows: ['alt'], mac: ['option']}"
716
749
  :data-testid="`menu-cluster-${ c.id }`"
717
- class="cluster selector option"
750
+ class="cluster selector option clusterBtn"
718
751
  :class="{'active-menu-link': c.isMenuActive }"
719
752
  :to="c.clusterRoute"
720
753
  role="button"
@@ -745,7 +778,9 @@ export default {
745
778
  :tab-order="shown ? 0 : -1"
746
779
  :cluster="c"
747
780
  />
748
- </button>
781
+ </span>
782
+
783
+ <!-- 不可用集群 -->
749
784
  <span
750
785
  v-else
751
786
  class="option cluster selector disabled"
@@ -777,7 +812,7 @@ export default {
777
812
  </div>
778
813
  </div>
779
814
 
780
- <!-- No clusters message -->
815
+ <!-- 无匹配集群提示 -->
781
816
  <div
782
817
  v-if="clustersFiltered.length === 0 && searchActive"
783
818
  data-testid="top-level-menu-no-results"
@@ -787,7 +822,7 @@ export default {
787
822
  </div>
788
823
  </div>
789
824
 
790
- <!-- See all clusters -->
825
+ <!-- 查看所有集群按钮 -->
791
826
  <router-link
792
827
  v-if="allClustersCount > maxClustersToShow"
793
828
  class="clusters-all"
@@ -806,104 +841,129 @@ export default {
806
841
  </router-link>
807
842
  </template>
808
843
 
809
- <!-- MULTI CLUSTER APPS -->
810
- <div class="category">
844
+ <!-- ====================== 多集群应用区 ====================== -->
845
+ <div :style="!(topLevelPermissions && topLevelPermissions === 'superadmin') ? { placeContent: 'flex-start', display: 'flex', flexDirection: 'column' } : {}" class="category">
846
+ <!-- 多集群应用 -->
811
847
  <template v-if="multiClusterApps.length">
812
- <div
813
- class="category-title"
814
- >
815
- <hr role="none">
816
- <span>
817
- {{ t('nav.categories.multiCluster') }}
818
- </span>
819
- </div>
820
- <div
821
- v-for="(a, i) in appBar.multiClusterApps"
822
- :key="i"
823
- @click="hide()"
824
- >
825
- <router-link
826
- class="option"
827
- :class="{'active-menu-link': a.isMenuActive }"
828
- :to="a.to"
829
- role="link"
830
- :aria-label="`${t('nav.ariaLabel.multiClusterApps')} ${ a.label }`"
831
- >
832
- <IconOrSvg
833
- v-clean-tooltip="getTooltipConfig(a.label)"
834
- class="app-icon"
835
- :icon="a.icon"
836
- :src="a.svg"
837
- />
838
- <span class="option-link">{{ a.label }}</span>
839
- </router-link>
840
- </div>
841
- </template>
842
-
843
- <!-- Configuration apps menu -->
844
- <template v-if="configurationApps.length">
845
- <div
846
- class="category-title"
847
- >
848
- <hr role="none">
849
- <span>
850
- {{ t('nav.categories.configuration') }}
851
- </span>
852
- </div>
853
- <div
854
- v-for="(a, i) in appBar.configurationApps"
855
- :key="i"
856
- @click="hide()"
857
- >
858
- <router-link
859
- class="option"
860
- :class="{'active-menu-link': a.isMenuActive }"
861
- :to="a.to"
862
- role="link"
863
- :aria-label="`${t('nav.ariaLabel.configurationApps')} ${ a.label }`"
848
+ <template v-if="topLevelPermissions && topLevelPermissions === 'superadmin'">
849
+ <div
850
+ class="category-title"
864
851
  >
865
- <IconOrSvg
866
- v-clean-tooltip="getTooltipConfig(a.label)"
867
- class="app-icon"
868
- :icon="a.icon"
869
- :src="a.svg"
870
- />
871
- <div>{{ a.label }}</div>
872
- </router-link>
873
- </div>
852
+ <hr role="none">
853
+ <span>
854
+ {{ t('nav.categories.multiCluster') }}
855
+ </span>
856
+ </div>
857
+ <template v-for="(a, i) in appBar.multiClusterApps" :key="i">
858
+ <div
859
+ v-if="a.value === 'harvesterManager'"
860
+ @click="hide()"
861
+ >
862
+ <router-link
863
+ class="option"
864
+ :class="{'active-menu-link': a.isMenuActive }"
865
+ :to="a.to"
866
+ role="link"
867
+ :aria-label="`${t('nav.ariaLabel.multiClusterApps')} ${ a.label }`"
868
+ >
869
+ <IconOrSvg
870
+ v-clean-tooltip="getTooltipConfig(a.label)"
871
+ class="app-icon"
872
+ :icon="a.icon"
873
+ :src="a.svg"
874
+ />
875
+ <span class="option-link">{{ a.label }}</span>
876
+ </router-link>
877
+ </div>
878
+ </template>
879
+ </template>
880
+ <template v-else>
881
+ <template v-for="(a, i) in appBar.multiClusterApps" :key="i">
882
+ <div
883
+ v-if="a.value === 'harvesterManager'"
884
+ @click="hide()"
885
+ >
886
+ <router-link
887
+ class="option"
888
+ :class="{'active-menu-link': a.isMenuActive }"
889
+ :to="a.to"
890
+ role="link"
891
+ :aria-label="`${t('nav.ariaLabel.multiClusterApps')} ${ a.label }`"
892
+ >
893
+ <IconOrSvg
894
+ v-clean-tooltip="getTooltipConfig(a.label)"
895
+ class="app-icon"
896
+ :icon="a.icon"
897
+ :src="a.svg"
898
+ />
899
+ <span class="option-link">{{ a.label }}</span>
900
+ </router-link>
901
+ </div>
902
+ </template>
903
+ </template>
874
904
  </template>
875
- </div>
876
- </div>
877
905
 
878
- <!-- Footer -->
879
- <div
880
- class="footer"
881
- >
882
- <div
883
- v-if="canEditSettings"
884
- class="support"
885
- @click="hide()"
886
- >
887
- <router-link
888
- :to="{name: 'support'}"
889
- role="link"
890
- :aria-label="t('nav.ariaLabel.support')"
891
- >
892
- {{ t('nav.support', {hasSupport}) }}
893
- </router-link>
894
- </div>
895
- <div
896
- class="version"
897
- :class="{'version-small': largeAboutText}"
898
- @click="hide()"
899
- >
900
- <router-link
901
- :to="{ name: 'about' }"
902
- role="link"
903
- :aria-label="t('nav.ariaLabel.about')"
904
- >
905
- {{ aboutText }}
906
- </router-link>
906
+ <!-- 配置类应用 -->
907
+ <div>
908
+ <template v-if="configurationApps.length">
909
+ <template v-if="topLevelPermissions && topLevelPermissions === 'superadmin'">
910
+ <div
911
+ class="category-title"
912
+ >
913
+ <hr role="none">
914
+ <span>
915
+ {{ t('nav.categories.configuration') }}
916
+ </span>
917
+ </div>
918
+ <div
919
+ v-for="(a, i) in appBar.configurationApps"
920
+ :key="i"
921
+ @click="hide()"
922
+ >
923
+ <router-link
924
+ class="option"
925
+ :class="{'active-menu-link': a.isMenuActive }"
926
+ :to="a.to"
927
+ role="link"
928
+ :aria-label="`${t('nav.ariaLabel.configurationApps')} ${ a.label }`"
929
+ >
930
+ <IconOrSvg
931
+ v-clean-tooltip="getTooltipConfig(a.label)"
932
+ class="app-icon"
933
+ :icon="a.icon"
934
+ :src="a.svg"
935
+ />
936
+ <div>{{ a.label }}</div>
937
+ </router-link>
938
+ </div>
939
+ </template>
940
+ <template v-else>
941
+ <template v-for="(a, i) in appBar.configurationApps" :key="i">
942
+ <div
943
+ v-if="a.value === 'settings' || a.value === 'auth'"
944
+ @click="hide()"
945
+ >
946
+ <router-link
947
+ class="option"
948
+ :class="{'active-menu-link': a.isMenuActive }"
949
+ :to="a.to"
950
+ role="link"
951
+ :aria-label="`${t('nav.ariaLabel.configurationApps')} ${ a.label }`"
952
+ >
953
+ <IconOrSvg
954
+ v-clean-tooltip="getTooltipConfig(a.label)"
955
+ class="app-icon"
956
+ :icon="a.icon"
957
+ :src="a.svg"
958
+ />
959
+ <div>{{ a.label }}</div>
960
+ </router-link>
961
+ </div>
962
+ </template>
963
+ </template>
964
+ <div style="height: 40px;"></div>
965
+ </template>
966
+ </div>
907
967
  </div>
908
968
  </div>
909
969
  </div>
@@ -962,6 +1022,10 @@ export default {
962
1022
  $option-padding-left: 14px;
963
1023
  $option-height: $icon-size + $option-padding + $option-padding;
964
1024
 
1025
+ .clusterBtn {
1026
+ background-color: var(--nav-icon-badge-bg);
1027
+ }
1028
+
965
1029
  .side-menu {
966
1030
  .menu {
967
1031
  position: absolute;
@@ -1058,7 +1122,6 @@ export default {
1058
1122
  flex: 1;
1059
1123
  display: flex;
1060
1124
  flex-direction: column;
1061
- margin: 10px 0;
1062
1125
  width: 300px;
1063
1126
  overflow: auto;
1064
1127
 
@@ -1066,7 +1129,7 @@ export default {
1066
1129
  align-items: center;
1067
1130
  cursor: pointer;
1068
1131
  display: flex;
1069
- color: var(--link);
1132
+ color: var(--primary);
1070
1133
  font-size: 14px;
1071
1134
  height: $option-height;
1072
1135
  white-space: nowrap;
@@ -1076,7 +1139,7 @@ export default {
1076
1139
  border: none;
1077
1140
 
1078
1141
  .cluster-badge-logo-text {
1079
- color: var(--default-active-text);
1142
+ color: var(--primary);
1080
1143
  font-weight: 500;
1081
1144
  }
1082
1145
 
@@ -1148,7 +1211,7 @@ export default {
1148
1211
  .rancher-provider-icon,
1149
1212
  svg {
1150
1213
  margin-right: 16px;
1151
- fill: var(--link);
1214
+ fill: var(--primary);
1152
1215
  }
1153
1216
 
1154
1217
  .top-menu-icon {
@@ -109,6 +109,7 @@ export default {
109
109
  </script>
110
110
 
111
111
  <template>
112
+ <!-- 当 type 有 route 时,渲染一个 Vue Router 自定义链接 -->
112
113
  <router-link
113
114
  v-if="type.route"
114
115
  :key="type.name"
@@ -116,18 +117,24 @@ export default {
116
117
  custom
117
118
  :to="type.route"
118
119
  >
120
+
121
+ <!-- 导航项容器 -->
119
122
  <li
120
123
  class="child nav-type"
121
124
  :class="{'root': isRoot, [`depth-${depth}`]: true, 'router-link-active': isActive, 'router-link-exact-active': isExactActive}"
122
125
  @click="navigate"
123
126
  @keypress.enter="navigate"
124
127
  >
128
+
129
+ <!-- 如果是精确匹配激活状态,则显示 TabTitle 组件 -->
125
130
  <TabTitle
126
131
  v-if="isExactActive"
127
132
  :show-child="false"
128
133
  >
129
134
  {{ type.labelKey ? t(type.labelKey) : (type.labelDisplay || type.label) }}
130
135
  </TabTitle>
136
+
137
+ <!-- 链接主体 -->
131
138
  <a
132
139
  role="link"
133
140
  :aria-label="type.labelKey ? t(type.labelKey) : (type.labelDisplay || type.label)"
@@ -138,30 +145,40 @@ export default {
138
145
  @mouseenter="setNear(true)"
139
146
  @mouseleave="setNear(false)"
140
147
  >
148
+ <!-- 文本标签:优先使用多语言 key -->
141
149
  <span
142
150
  v-if="type.labelKey"
143
151
  class="label"
144
152
  ><t :k="type.labelKey" /></span>
145
- <span
146
- v-else
147
- v-clean-html="type.labelDisplay || type.label"
148
- class="label"
149
- :class="{'no-icon': !type.icon}"
150
- />
153
+
154
+ <!-- 没有 labelKey 时,直接使用 HTML 文本 -->
155
+ <div v-else style="display: flex; align-items: center;" class="labelKey_menu">
156
+ <i v-if="!type.labelDisplay || (type.labelDisplay && type.labelDisplay.indexOf('</i>') === -1)" class="icon icon-fw icon-globe" style="color: var(--muted);width: 32px;text-align: left;"></i>
157
+ <span
158
+ v-clean-html="type.labelDisplay.replace('设置', '基础设置') || type.label"
159
+ class="label"
160
+ :class="{'no-icon': !type.icon}"
161
+ />
162
+ </div>
163
+
164
+ <!-- 右侧附加信息(收藏按钮 / 命名空间图标 / 计数) -->
151
165
  <!-- <span
152
166
  v-if="showFavorite || namespaceIcon || showCount"
153
167
  class="count"
154
168
  >
169
+
155
170
  <Favorite
156
171
  v-if="showFavorite"
157
172
  :resource="type.name"
158
173
  />
174
+
159
175
  <i
160
176
  v-if="namespaceIcon"
161
177
  class="icon icon-namespace"
162
178
  :class="{'ns-and-icon': showCount}"
163
179
  data-testid="type-namespaced"
164
180
  />
181
+
165
182
  <span
166
183
  v-if="showCount"
167
184
  data-testid="type-count"
@@ -170,6 +187,8 @@ export default {
170
187
  </a>
171
188
  </li>
172
189
  </router-link>
190
+
191
+ <!-- 当 type 没有 route 但有外部 link 时 -->
173
192
  <li
174
193
  v-else-if="type.link"
175
194
  class="child nav-type nav-link"
@@ -185,6 +204,8 @@ export default {
185
204
  <span class="label">{{ type.label }}&nbsp;<i class="icon icon-external-link" /></span>
186
205
  </a>
187
206
  </li>
207
+
208
+ <!-- 兜底情况:既没有 route,也没有 link -->
188
209
  <li v-else>
189
210
  {{ type }}?
190
211
  </li>
@@ -234,12 +255,12 @@ export default {
234
255
  A {
235
256
  display: grid;
236
257
  grid-template-areas: "label count";
237
- grid-template-columns: auto auto;
258
+ grid-template-columns: auto 20px;
238
259
  grid-column-gap: 5px;
239
260
  font-size: 14px;
240
261
  line-height: 24px;
241
262
  /* padding: 7.5px 7px 7.5px 10px; */
242
- padding: 0px 16px 0px 40px;
263
+ padding: 0px 16px 0px 30px;
243
264
  height: 50px;
244
265
  margin: 0 0 0 -3px;
245
266
  overflow: hidden;
@@ -248,7 +269,7 @@ export default {
248
269
  color: var(--body-text);
249
270
 
250
271
  &:hover {
251
- background: var(--nav-active);
272
+ background: var(--nav-active) !important;
252
273
  color: var(--nav-hover-color);
253
274
  /* background: var(--nav-hover); */
254
275
  text-decoration: none;
@@ -271,13 +292,13 @@ export default {
271
292
  font-size: 12px;
272
293
  text-align: right;
273
294
  justify-items: center;
274
- padding-right: 4px;
295
+ line-height: 50px;
275
296
  }
276
297
 
277
298
  &.nav-type:not(.depth-0) {
278
299
  A {
279
300
  font-size: 13px;
280
- padding: 5.5px 7px 5.5px 10px;
301
+ padding: 5.5px 7px 5.5px 40px;
281
302
  }
282
303
 
283
304
  ::v-deep .label I {
@@ -286,4 +307,20 @@ export default {
286
307
  }
287
308
  }
288
309
 
310
+ .labelKey_menu{
311
+ display: flex;
312
+ align-items: center;
313
+ }
314
+ .labelKey_menu:hover{
315
+ i{
316
+ color: var(--nav-hover-color) !important;
317
+ }
318
+ }
319
+ .router-link-active{
320
+ .labelKey_menu{
321
+ i{
322
+ color: var(--nav-hover-color) !important;
323
+ }
324
+ }
325
+ }
289
326
  </style>
@@ -76,6 +76,6 @@ export const useClickOutside = <T extends OnClickOutsideOptions>(
76
76
 
77
77
  onBeforeUnmount(() => {
78
78
  window.removeEventListener('click', listener as any);
79
- window.removeEventListener('pointerDown', setShouldListen);
79
+ window.removeEventListener('pointerdown', setShouldListen);
80
80
  });
81
81
  };