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
@@ -47,6 +47,11 @@ export default {
47
47
  }
48
48
  },
49
49
 
50
+ isManuallyHide: {
51
+ type: Boolean,
52
+ default: true
53
+ },
54
+
50
55
  mode: {
51
56
  type: String,
52
57
  default: 'create'
@@ -250,7 +255,7 @@ export default {
250
255
  },
251
256
 
252
257
  parent() {
253
- const displayName = this.value?.parentNameOverride || this.$store.getters['type-map/labelFor'](this.schema);
258
+ let displayName = this.value?.parentNameOverride || this.$store.getters['type-map/labelFor'](this.schema);
254
259
  const product = this.$store.getters['currentProduct'].name;
255
260
 
256
261
  const defaultLocation = {
@@ -268,6 +273,20 @@ export default {
268
273
  }
269
274
 
270
275
  const typeOptions = this.$store.getters[`type-map/optionsFor`]( this.resource );
276
+
277
+ // 转换为中文
278
+ const displayName_zh_hans = {
279
+ 'GlobalRole': '全局角色',
280
+ 'RoleTemplate': '集群角色',
281
+ }
282
+ if (displayName_zh_hans[displayName]) {
283
+ displayName = displayName_zh_hans[displayName]
284
+ }
285
+
286
+ if (displayName == '集群角色' && (this.$route.query?.roleContext == 'NAMESPACE' || location.hash == '#NAMESPACE')) {
287
+ displayName = '项目或资源组角色'
288
+ }
289
+
271
290
  const out = {
272
291
  displayName, location, ...typeOptions
273
292
  };
@@ -318,12 +337,12 @@ export default {
318
337
  });
319
338
  }
320
339
 
321
- if ( this.canViewYaml ) {
322
- out.push({
323
- labelKey: 'resourceDetail.masthead.yaml',
324
- value: _YAML,
325
- });
326
- }
340
+ // if ( this.canViewYaml ) {
341
+ // out.push({
342
+ // labelKey: 'resourceDetail.masthead.yaml',
343
+ // value: _YAML,
344
+ // });
345
+ // }
327
346
 
328
347
  if ( out.length < 2 ) {
329
348
  return null;
@@ -422,7 +441,7 @@ export default {
422
441
  },
423
442
  menuIcon() {
424
443
  const product = this.$store.getters['productId'];
425
-
444
+
426
445
  const resources = this.location?.params?.resource || ''
427
446
 
428
447
  return this.$store.getters['type-map/groupsForVirTypes'](product, resources);
@@ -473,263 +492,192 @@ export default {
473
492
  </script>
474
493
 
475
494
  <template>
495
+
496
+ <!-- 顶部区域的容器 -->
476
497
  <div class="masthead">
477
498
  <div class="title">
478
- <!-- 创建api密钥不需要面包屑 -->
479
- <div
499
+
500
+ <!-- 面包屑导航(创建 API 密钥时不显示) -->
501
+ <!-- <div
480
502
  v-if="!(parentRouteOverride === 'account' && resource=== 'token')"
481
503
  class="excram-list"
482
504
  >
505
+
506
+ 遍历 demoDisplay 生成面包屑路径
483
507
  <span
484
508
  v-for="(item,index) in demoDisplay"
485
509
  :key="index"
486
510
  >
487
- <span>{{ item }}</span>
488
- <span>/</span>
511
+ <span v-if="item">{{ item }}</span>
512
+ <span v-if="item">/</span>
489
513
  </span>
514
+
515
+ 最后一个面包屑显示当前操作(查看/编辑/创建)+ 父资源名称
490
516
  <span class="excram-last-name">
491
517
  {{ (realMode === 'view'? '查看': realMode === 'edit' ? '编辑':'创建') + parent.displayName }}
492
518
  </span>
493
- </div>
494
- <header>
495
- <div class="title">
496
- <div class="primaryheader">
497
- <span class="primary-title">
498
- <!-- <nuxt-link
499
- v-if="location"
500
- :to="location"
501
- >
502
- {{ parent.displayName }}:
503
- </nuxt-link> -->
504
- <span class="detailIcon-span">
505
- <img
506
- v-if="parentRouteOverride === 'account' && resource=== 'token'"
507
- :src="Svg"
508
- style="margin-top: 4px; margin-left: 5px;"
509
- >
510
- <i
511
- v-else
512
- :class="'icon-'+ menuIcon + ' detailIcon'"
513
- />
514
- </span>
515
- <span class="detailIcon-span-title">{{ realMode=== 'create'? '创建': '' }}{{ parent.displayName }}{{ realMode=== 'create'? '': '名称:' }}</span>
516
- <span v-if="realMode !== 'create'">
517
- <span v-if="value.detailPageHeaderActionOverride && value.detailPageHeaderActionOverride(realMode)">{{ value.detailPageHeaderActionOverride(realMode) }}</span>
518
- <t
519
- v-else
520
- :k="'resourceDetail.header.' + realMode"
521
- :subtype="resourceSubtype"
522
- :name="displayName"
523
- :escapehtml="false"
519
+ </div> -->
520
+
521
+ <header>
522
+ <div class="title">
523
+ <div class="primaryheader">
524
+ <span class="primary-title">
525
+
526
+ <!-- 图标区 -->
527
+ <span v-if="menuIcon && !(parentRouteOverride === 'account' && resource=== 'token')" class="detailIcon-span">
528
+ <!-- 如果是账户 API token,则显示图片,否则显示 icon -->
529
+ <img
530
+ v-if="parentRouteOverride === 'account' && resource=== 'token'"
531
+ :src="Svg"
532
+ style="margin-top: 4px; margin-left: 5px;"
533
+ >
534
+ <i
535
+ v-else
536
+ :class="'icon-'+ menuIcon + ' detailIcon'"
537
+ />
538
+ </span>
539
+
540
+ <!-- 资源标题(创建时只显示“创建+名称”,否则显示“名称:”) -->
541
+ <span class="detailIcon-span-title">{{ realMode=== 'create'? '创建': '' }}{{ parent.displayName }}{{ realMode=== 'create'? '': '名称:' }}</span>
542
+
543
+ <!-- 如果不是创建模式,显示操作描述 -->
544
+ <span v-if="realMode !== 'create'">
545
+
546
+ <!-- 如果有覆盖方法,优先显示覆盖内容 -->
547
+ <span v-if="value.detailPageHeaderActionOverride && value.detailPageHeaderActionOverride(realMode)">{{ value.detailPageHeaderActionOverride(realMode) }}</span>
548
+
549
+ <!-- 否则用 t 组件国际化显示 -->
550
+ <t
551
+ v-else
552
+ :k="'resourceDetail.header.' + realMode"
553
+ :subtype="resourceSubtype"
554
+ :name="displayName"
555
+ :escapehtml="false"
556
+ />
557
+ </span>
558
+
559
+ <!-- 状态点(DotState 组件) -->
560
+ <DotState
561
+ v-if="!isCreate && parent.showState"
562
+ class="masthead-state"
563
+ :value="value"
524
564
  />
565
+
566
+ <!-- Istio 注入状态 -->
567
+ <span
568
+ v-if="!isCreate && value.injectionEnabled"
569
+ class="masthead-istio"
570
+ >
571
+ <i
572
+ v-clean-tooltip="t('projectNamespaces.isIstioInjectionEnabled')"
573
+ class="icon icon-sm icon-istio"
574
+ />
575
+ </span>
525
576
  </span>
526
- <DotState
527
- v-if="!isCreate && parent.showState"
528
- class="masthead-state"
529
- :value="value"
530
- />
577
+
578
+ <!-- 如果有返回路径,显示分隔符和“返回”链接 -->
531
579
  <span
532
- v-if="!isCreate && value.injectionEnabled"
533
- class="masthead-istio"
580
+ v-if="location"
581
+ class="valid"
582
+ >|</span>
583
+ <router-link
584
+ v-if="location"
585
+ :to="location"
534
586
  >
535
- <i
536
- v-clean-tooltip="t('projectNamespaces.isIstioInjectionEnabled')"
537
- class="icon icon-sm icon-istio"
538
- />
539
- </span>
540
- </span>
541
- <span
542
- v-if="location"
543
- class="valid"
544
- >|</span>
545
- <router-link
546
- v-if="location"
547
- :to="location"
548
- >
549
- 返回
550
- </router-link>
551
- <!-- <h1>
552
- <TabTitle
553
- v-if="isCreate"
554
- :showChild="false"
555
- >
556
- {{ parent.displayName }}
557
- </TabTitle>
558
- <TabTitle
559
- v-else
560
- :showChild="false"
561
- >
562
- {{ displayName }}
563
- </TabTitle>
564
- <router-link
565
- v-if="location"
566
- :to="location"
567
- role="link"
568
- class="masthead-resource-list-link"
569
- :aria-label="parent.displayName"
570
- >
571
- {{ parent.displayName }}:
572
- </router-link>
573
- <span v-else>{{ parent.displayName }}:</span>
574
- <span v-if="value?.detailPageHeaderActionOverride && value?.detailPageHeaderActionOverride(realMode)">{{ value?.detailPageHeaderActionOverride(realMode) }}</span>
575
- <t
576
- v-else
577
- class="masthead-resource-title"
578
- :k="'resourceDetail.header.' + realMode"
579
- :subtype="resourceSubtype"
580
- :name="displayName"
581
- :escapehtml="false"
582
- />
583
- <BadgeState
584
- v-if="!isCreate && parent.showState"
585
- class="masthead-state"
586
- :value="value"
587
- />
588
- <span
589
- v-if="!isCreate && value.injectionEnabled"
590
- class="masthead-istio"
591
- >
592
- <i
593
- v-clean-tooltip="t('projectNamespaces.isIstioInjectionEnabled')"
594
- class="icon icon-sm icon-istio"
595
- />
596
- </span>
597
- <a
598
- v-if="dev && !!resourceExternalLink"
599
- v-clean-tooltip="t(resourceExternalLink.tipsKey || 'generic.resourceExternalLinkTips')"
600
- class="resource-external"
601
- rel="nofollow noopener noreferrer"
602
- target="_blank"
603
- :href="resourceExternalLink.url"
604
- >
605
- <i class="icon icon-external-link" />
606
- </a>
607
- </h1> -->
587
+ 返回
588
+ </router-link>
589
+ </div>
608
590
  </div>
609
- <!-- <div
610
- v-if="!isCreate"
611
- class="subheader"
612
- >
613
- <span v-if="isNamespace && project">{{ t("resourceDetail.masthead.project") }}: <router-link :to="project.detailLocation">{{ project.nameDisplay }}</router-link></span>
614
- <span v-else-if="isWorkspace">{{ t("resourceDetail.masthead.workspace") }}: <router-link :to="workspaceLocation">{{ namespace }}</router-link></span>
615
- <span v-else-if="namespace && !hasMultipleNamespaces">
616
- {{ t("resourceDetail.masthead.namespace") }}:
617
- <router-link
618
- v-if="!hideNamespaceLocation"
619
- :to="namespaceLocation"
620
- data-testid="masthead-subheader-namespace"
621
- >
622
- {{ namespace }}
623
- </router-link>
624
- <span v-else>
625
- {{ namespace }}
626
- </span>
627
- </span>
628
- <span v-if="parent.showAge">
629
- {{ t("resourceDetail.masthead.age") }}:
630
- <LiveDate
631
- class="live-date"
632
- :value="value.creationTimestamp"
633
- />
634
- </span>
635
- <span
636
- v-if="value.showCreatedBy"
637
- data-testid="masthead-subheader-createdBy"
638
- >
639
- {{ t("resourceDetail.masthead.createdBy") }}:
640
- <router-link
641
- v-if="value.createdBy.location"
642
- :to="value.createdBy.location"
643
- data-testid="masthead-subheader-createdBy-link"
644
- >
645
- {{ value.createdBy.displayName }}
646
- </router-link>
647
- <span
648
- v-else
649
- data-testid="masthead-subheader-createdBy_plain-text"
650
- >
651
- {{ value.createdBy.displayName }}
652
- </span>
653
- </span>
654
- <span v-if="value.showPodRestarts">{{ t("resourceDetail.masthead.restartCount") }}:<span class="live-data"> {{ value.restartCount }}</span></span>
655
- </div> -->
656
- </div>
657
- <slot name="right">
658
- <div class="actions-container align-start">
659
- <div class="actions">
660
- <button
661
- v-if="detailsAction && currentView === DETAIL_VIEW && isView"
662
- type="button"
663
- class="btn role-primary actions mr-10"
664
- :disabled="!detailsAction.enabled"
665
- @click="invokeDetailsAction"
666
- >
667
- {{ detailsAction.label }}
668
- </button>
669
- <ButtonGroup
670
- v-if="showSensitiveToggle"
671
- :value="!!hideSensitiveData"
672
- icon-size="lg"
673
- :options="sensitiveOptions"
674
- class="mr-10"
675
- @update:value="toggleSensitiveData"
676
- />
677
-
678
- <ButtonGroup
679
- v-if="viewOptions && isView"
680
- v-model:value="currentView"
681
- :options="viewOptions"
682
- class="mr-10"
683
- />
684
-
685
- <template v-if="featureDropdownMenu">
686
- <ActionMenu
687
- v-if="isView"
688
- button-role="multiAction"
689
- button-size="compact"
690
- :resource="value"
691
- data-testid="masthead-action-menu"
692
- />
693
- </template>
694
- <template v-else>
591
+
592
+ <!-- 右侧操作按钮区域(支持通过 slot 覆盖) -->
593
+ <slot name="right">
594
+ <div class="actions-container align-start" style="padding-right: 15px;">
595
+ <div class="actions">
596
+
597
+ <!-- 详情模式下的主操作按钮 -->
695
598
  <button
696
- v-if="isView"
697
- ref="actions"
698
- data-testid="masthead-action-menu"
699
- aria-haspopup="true"
599
+ v-if="detailsAction && currentView === DETAIL_VIEW && isView && isManuallyHide"
700
600
  type="button"
701
- class="btn role-multi-action actions"
702
- @click="showActions"
601
+ class="btn role-primary actions mr-10"
602
+ :disabled="!detailsAction.enabled"
603
+ @click="invokeDetailsAction"
703
604
  >
704
- <i class="icon icon-actions" />
605
+ {{ detailsAction.label }}
705
606
  </button>
706
- </template>
607
+
608
+ <!-- 敏感信息显示/隐藏切换 -->
609
+ <ButtonGroup
610
+ v-if="showSensitiveToggle"
611
+ :value="!!hideSensitiveData"
612
+ icon-size="lg"
613
+ :options="sensitiveOptions"
614
+ class="mr-10"
615
+ @update:value="toggleSensitiveData"
616
+ />
617
+
618
+ <!-- 视图切换按钮 -->
619
+ <ButtonGroup
620
+ v-if="viewOptions && isView"
621
+ v-model:value="currentView"
622
+ :options="viewOptions"
623
+ class="mr-10"
624
+ />
625
+
626
+ <!-- 功能菜单:优先使用 ActionMenu 组件 -->
627
+ <template v-if="featureDropdownMenu">
628
+ <ActionMenu
629
+ v-if="isView"
630
+ button-role="multiAction"
631
+ button-size="compact"
632
+ :resource="value"
633
+ data-testid="masthead-action-menu"
634
+ />
635
+ </template>
636
+
637
+ <!-- 如果没有 featureDropdownMenu,则使用普通的多操作按钮 -->
638
+ <template v-else>
639
+ <button
640
+ v-if="isView"
641
+ ref="actions"
642
+ data-testid="masthead-action-menu"
643
+ aria-haspopup="true"
644
+ type="button"
645
+ class="btn role-multi-action actions"
646
+ @click="showActions"
647
+ >
648
+ <i class="icon icon-actions" />
649
+ </button>
650
+ </template>
651
+ </div>
707
652
  </div>
708
- </div>
709
- </slot>
710
- </header>
711
-
712
- <!-- Extension area -->
713
- <ExtensionPanel
714
- :resource="value"
715
- :type="extensionType"
716
- :location="extensionLocation"
717
- />
718
-
719
- <Banner
720
- v-if="banner && isView && !parent.hideBanner"
721
- class="state-banner mb-10"
722
- :color="banner.color"
723
- :label="banner.message"
724
- />
725
- <Banner
726
- v-if="managedWarning.show"
727
- color="warning"
728
- class="mb-20"
729
- :label="t('resourceDetail.masthead.managedWarning', managedWarning)"
730
- />
731
-
732
- <slot />
653
+ </slot>
654
+ </header>
655
+
656
+ <!-- 扩展区域 -->
657
+ <ExtensionPanel
658
+ :resource="value"
659
+ :type="extensionType"
660
+ :location="extensionLocation"
661
+ />
662
+
663
+ <!-- 顶部状态 Banner -->
664
+ <Banner
665
+ v-if="banner && isView && !parent.hideBanner"
666
+ class="state-banner mb-10"
667
+ :color="banner.color"
668
+ :label="banner.message == 'Waiting for API to be available' ? '等待 API 可用' : banner.message"
669
+ />
670
+
671
+ <!-- 管理警告 Banner -->
672
+ <Banner
673
+ v-if="managedWarning.show"
674
+ color="warning"
675
+ class="mb-20"
676
+ :label="t('resourceDetail.masthead.managedWarning', managedWarning)"
677
+ />
678
+
679
+ <!-- 内容插槽 -->
680
+ <slot />
733
681
  </div>
734
682
  </div>
735
683
  </template>
@@ -457,8 +457,13 @@ export default {
457
457
  </script>
458
458
 
459
459
  <template>
460
+
461
+ <!-- 如果数据还在加载中,或者资源未找到,则显示 Loading 组件 -->
460
462
  <Loading v-if="$fetchState.pending || notFound" />
461
- <div v-else>
463
+
464
+ <!-- 数据加载完成且资源存在时 -->
465
+ <div style="padding: 20px 0 20px 20px;height: 100%;" v-else>
466
+ <!-- 顶部 Masthead 区域 -->
462
467
  <Masthead
463
468
  v-if="showMasthead"
464
469
  :resource="resourceType"
@@ -469,20 +474,25 @@ export default {
469
474
  :has-graph="hasGraph"
470
475
  :has-detail="hasCustomDetail"
471
476
  :has-edit="hasCustomEdit"
477
+ :can-view-yaml="canViewYaml"
472
478
  :resource-subtype="resourceSubtype"
473
479
  :parent-route-override="parentRouteOverride"
474
480
  :store-override="storeOverride"
481
+
482
+ :isManuallyHide="false"
475
483
  >
476
- <!-- <DetailTop
477
- v-if="isView && isDetail"
478
- :value="liveModel"
479
- /> -->
484
+
480
485
  </Masthead>
486
+
487
+
488
+ <!-- 错误信息显示区域 -->
481
489
  <div
482
490
  v-if="hasErrors"
483
491
  id="cru-errors"
484
492
  class="cru__errors"
485
493
  >
494
+
495
+ <!-- 循环渲染错误 Banner -->
486
496
  <Banner
487
497
  v-for="(err, i) in errors"
488
498
  :key="i"
@@ -495,12 +505,14 @@ export default {
495
505
  />
496
506
  </div>
497
507
 
508
+ <!-- 力导向图模式 -->
498
509
  <ForceDirectedTreeChart
499
510
  v-if="isGraph && canViewChart"
500
511
  :data="chartData"
501
512
  :fdc-config="getGraphConfig"
502
513
  />
503
514
 
515
+ <!-- YAML 查看/编辑模式 -->
504
516
  <ResourceYaml
505
517
  v-else-if="isYaml"
506
518
  ref="resourceyaml"
@@ -514,6 +526,7 @@ export default {
514
526
  @error="e=>errors.push(e)"
515
527
  />
516
528
 
529
+ <!-- 动态组件渲染,根据 showComponent 动态选择组件 -->
517
530
  <component
518
531
  :is="showComponent"
519
532
  v-else
@@ -532,6 +545,8 @@ export default {
532
545
  @set-subtype="setSubtype"
533
546
  />
534
547
 
548
+
549
+ <!-- 快捷键按钮(隐藏) -->
535
550
  <button
536
551
  v-if="isView"
537
552
  v-shortkey.once="['shift','d']"