dashboard-shell-shell 3.0.5-test.46 → 3.0.5-test.50

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.
@@ -7648,6 +7648,10 @@ typeDescription:
7648
7648
  management.cattle.io.setting: 统一配置平台基础选项与全局设置,支持CA证书、密码规则、域名、Token时效等核心配置。
7649
7649
  management.cattle.io.user: 用于管理用户账号,支持创建、维护用户信息,可设置用户权限、管理密码等,保障系统资源仅由授权用户访问,提升系统安全性。
7650
7650
  harvesterhci.io.management.cluster: 提供虚拟化集群的实时健康状态监控、版本号管理及资源负载管理,支持批量导入/删除集群、配置调优与权限分级功能,实现高效运维管控。
7651
+ harvesterhci.io.logging.clusterflow: 集群流用于展示集群内的事件与操作日志,帮助您实时监控集群状态、追踪资源变更,提升问题排查与运维效率。
7652
+ harvesterhci.io.logging.clusteroutput: 集群输出用于集中展示集群运行过程中的日志与输出信息,帮助您分析系统行为、定位问题并优化集群性能。
7653
+ harvesterhci.io.logging.flow: 流用于实时展示系统内各类事件与操作记录,帮助您监控资源变化、追踪操作过程,提升系统可观测性与运维效率。
7654
+ harvesterhci.io.logging.output: 输出用于查看系统或服务运行产生的日志与结果信息,帮助您及时了解运行状态并进行故障排查。
7651
7655
  typeLabel:
7652
7656
  management.cattle.io.oidcclient: |-
7653
7657
  {count, plural,
@@ -3264,6 +3264,18 @@ members:
3264
3264
  viewClusterCatalogs: 查看集群应用商店
3265
3265
  viewClusterMembers: 查看集群成员
3266
3266
  viewNodes: 查看节点
3267
+ safe-admin:
3268
+ label: 安全管理员
3269
+ description: 负责用户、角色及基础配置管理,保障系统权限与安全策略的合规性。
3270
+ project-tenant:
3271
+ label: 租户
3272
+ description: 租户可管理资源组及其中的虚机、网络等资源。
3273
+ cluster-tenant:
3274
+ label: 租户
3275
+ description: 租户可管理资源组及其中的虚机、网络等资源。
3276
+ tenant:
3277
+ label: 租户
3278
+ description: 租户可管理资源组及其中的虚机、网络等资源。
3267
3279
  owner:
3268
3280
  label: 所有者
3269
3281
  description: 所有者对集群和集群内的所有资源拥有完全的控制权。
@@ -3821,6 +3833,7 @@ node:
3821
3833
  operatingSystem: 操作系统
3822
3834
  osImage: 镜像
3823
3835
  systemUUID: 系统 UUID
3836
+ swap: 内存交换区
3824
3837
  pods: Pod
3825
3838
  taints: 污点
3826
3839
  actions:
@@ -4489,6 +4502,12 @@ projectMembers:
4489
4502
  description: 控制用户对项目的访问权限
4490
4503
  noDescription: 已创建用户 - 没有描述
4491
4504
  searchForMember: 搜索需要向其提供项目访问权限的成员
4505
+ safe-admin:
4506
+ label: 安全管理员
4507
+ description: 负责用户、角色及基础配置管理,保障系统权限与安全策略的合规性。
4508
+ tenant:
4509
+ label: 租户
4510
+ description: 租户可管理资源组及其中的虚机、网络等资源。
4492
4511
  owner:
4493
4512
  label: 所有者
4494
4513
  description: 所有者对项目和项目内的所有资源拥有完全的控制权限。
@@ -4752,6 +4771,9 @@ rbac:
4752
4771
  description: 无描述
4753
4772
  assignOnlyRole: 已分配该角色
4754
4773
  role:
4774
+ cluster-tenant:
4775
+ label: 租户
4776
+ description: 租户可管理资源组及其中的虚机、网络等资源。
4755
4777
  admin:
4756
4778
  label: 管理员
4757
4779
  description: 管理员可以完全控制整个安装以及所有集群中的所有资源。
@@ -4761,6 +4783,12 @@ rbac:
4761
4783
  user-base:
4762
4784
  label: User-Base 用户
4763
4785
  description: User-Base 用户只拥有登录权限。
4786
+ tenant:
4787
+ label: 租户
4788
+ description: 租户可管理资源组及其中的虚机、网络等资源。
4789
+ safe-admin:
4790
+ label: 安全管理员
4791
+ description: 负责用户、角色及基础配置管理,保障系统权限与安全策略的合规性。
4764
4792
  clusters-create:
4765
4793
  label: 创建集群
4766
4794
  description: 允许用户创建集群,并成为该集群的所有者(owner)。普通用户默认拥有此权限。
@@ -6531,6 +6559,7 @@ model:
6531
6559
  label: Service Account 用户名
6532
6560
  projectMember:
6533
6561
  role:
6562
+ tenant: 租户
6534
6563
  member: 成员
6535
6564
  owner: 所有者
6536
6565
  readonly: 只读用户
@@ -6626,6 +6655,10 @@ typeDescription:
6626
6655
  batch.cronjob: CronJob 创建 Job,然后按照重复调度来运行 Pod。该调度以标准的 Unix cron 格式表示,并使用 Kubernetes Control Plane 的时区(通常是 UTC)。
6627
6656
  batch.job: Job 创建一个或多个 Pod。 Job 通过运行 Pod 直到其成功退出,以可靠执行一次性任务。失败的 Pod 会自动被替换,直到达到指定的完成运行次数。Job 还可以并行运行多个 Pod,或作为批处理工作队列。
6628
6657
  pod: Pod 是你可以在 Kubernetes 中创建和管理的最小可部署计算单元。Pod 是一个或多个容器,具有共享的存储和网络资源以及运行容器的规范。
6658
+ harvesterhci.io.logging.clusterflow: 集群流用于展示集群内的事件与操作日志,帮助您实时监控集群状态、追踪资源变更,提升问题排查与运维效率。
6659
+ harvesterhci.io.logging.clusteroutput: 集群输出用于集中展示集群运行过程中的日志与输出信息,帮助您分析系统行为、定位问题并优化集群性能。
6660
+ harvesterhci.io.logging.flow: 流用于实时展示系统内各类事件与操作记录,帮助您监控资源变化、追踪操作过程,提升系统可观测性与运维效率。
6661
+ harvesterhci.io.logging.output: 输出用于查看系统或服务运行产生的日志与结果信息,帮助您及时了解运行状态并进行故障排查。
6629
6662
  typeLabel:
6630
6663
  management.cattle.io.project: |-
6631
6664
  {count, plural,
@@ -8074,3 +8107,13 @@ component:
8074
8107
  keyValue:
8075
8108
  noRows: 此资源上没有配置{propertyName}.
8076
8109
  showConfiguration: 显示配置
8110
+
8111
+
8112
+
8113
+ customConversion:
8114
+ Tenant: 租户
8115
+ Cluster Owner: 所有者
8116
+ Project Owner: 项目负责人
8117
+
8118
+
8119
+
@@ -135,7 +135,7 @@ export default {
135
135
  :amountTemplateValues="amountTemplateValues"
136
136
  :formattedPercentage="formattedPercentage"
137
137
  >
138
- <p>{{ formattedPercentage + '(共' + amountTemplateValues.total + ' ' + amountTemplateValues.unit + ',' + reserveText + ' ' + amountTemplateValues.used + ' ' + amountTemplateValues.unit + ')' }}</p>
138
+ <p>{{ formattedPercentage + '(共' + (amountTemplateValues.total || 0) + ' ' + (amountTemplateValues.unit || 'GiB') + ',' + (reserveText || '') + ' ' + (amountTemplateValues.used || 0) + ' ' + (amountTemplateValues.unit || 'GiB') + ')' }}</p>
139
139
  </slot>
140
140
  </div>
141
141
  </template>
@@ -103,20 +103,36 @@ export default {
103
103
  this.sortedRoles.global.push(...remainingGlobalRoles);
104
104
  // End sort of global roles
105
105
 
106
- delete this.sortedRoles.builtin
106
+ if (!(sessionStorage.getItem('TOPLEVELPERMISSIONS') && sessionStorage.getItem('TOPLEVELPERMISSIONS') === 'superadmin')) {
107
+ delete this.sortedRoles.builtin
108
+ delete this.sortedRoles.custom
109
+ }
107
110
 
108
111
  this.update();
109
112
  }
110
113
  } catch (e) { }
111
114
  },
112
115
  data() {
113
- return {
114
- // This not only identifies global roles but the order here is the order we want to display them in the UI
115
- globalPermissions: [
116
+
117
+ let globalPermissions = [
118
+ 'admin',
119
+ 'safe-admin',
120
+ 'tenant',
121
+ ]
122
+
123
+ if (sessionStorage.getItem('TOPLEVELPERMISSIONS') === 'superadmin') {
124
+ globalPermissions = [
116
125
  'admin',
126
+ 'safe-admin',
117
127
  'user',
118
128
  'user-base',
119
- ],
129
+ 'tenant',
130
+ ]
131
+ }
132
+
133
+ return {
134
+ // This not only identifies global roles but the order here is the order we want to display them in the UI
135
+ globalPermissions,
120
136
  globalRoleBindings: null,
121
137
  sortedRoles: null,
122
138
  selectedRoles: [],
@@ -312,6 +312,12 @@ export default {
312
312
  this.done();
313
313
  } catch (err) {
314
314
  this.error = err.message || err;
315
+ if (this.error.includes('not supported')) {
316
+ this.$store.dispatch('growl/error', {
317
+ title: '权限不足',
318
+ message: '当前用户不允许删除集群'
319
+ }, { root: true });
320
+ }
315
321
  btnCB(false);
316
322
  }
317
323
  },
@@ -143,30 +143,46 @@ export default {
143
143
  return [this.permissionGroup];
144
144
  },
145
145
  options() {
146
+
146
147
  const customRoles = this.customRoles.map((role) => ({
147
148
  label: role.nameDisplay,
148
149
  description: role.description || role.metadata?.annotations?.[DESCRIPTION] || this.t('members.clusterPermissions.noDescription'),
149
150
  value: role.id
150
151
  }));
151
152
 
152
- return [
153
- {
154
- label: this.t('members.clusterPermissions.owner.label'),
155
- description: this.t('members.clusterPermissions.owner.description'),
156
- value: 'owner'
157
- },
158
- {
159
- label: this.t('members.clusterPermissions.member.label'),
160
- description: this.t('members.clusterPermissions.member.description'),
161
- value: 'member'
162
- },
163
- ...customRoles,
164
- // {
165
- // label: this.t('members.clusterPermissions.custom.label'),
166
- // description: this.t('members.clusterPermissions.custom.description'),
167
- // value: 'custom'
168
- // }
169
- ];
153
+ let optionList = [{
154
+ label: this.t('members.clusterPermissions.cluster-tenant.label'),
155
+ description: this.t('members.clusterPermissions.cluster-tenant.description'),
156
+ value: 'cluster-tenant'
157
+ }];
158
+
159
+ if (sessionStorage.getItem('TOPLEVELPERMISSIONS') === 'superadmin') {
160
+ optionList = [
161
+ {
162
+ label: this.t('members.clusterPermissions.cluster-tenant.label'),
163
+ description: this.t('members.clusterPermissions.cluster-tenant.description'),
164
+ value: 'cluster-tenant'
165
+ },
166
+ {
167
+ label: this.t('members.clusterPermissions.owner.label'),
168
+ description: this.t('members.clusterPermissions.owner.description'),
169
+ value: 'owner'
170
+ },
171
+ {
172
+ label: this.t('members.clusterPermissions.member.label'),
173
+ description: this.t('members.clusterPermissions.member.description'),
174
+ value: 'member'
175
+ },
176
+ ...customRoles,
177
+ {
178
+ label: this.t('members.clusterPermissions.custom.label'),
179
+ description: this.t('members.clusterPermissions.custom.description'),
180
+ value: 'custom'
181
+ }
182
+ ];
183
+ }
184
+
185
+ return optionList
170
186
  },
171
187
  principal() {
172
188
  const principalId = this.principalId.replace(/\//g, '%2F');
@@ -191,7 +191,7 @@ export default {
191
191
  :data-testid="`role-item-${i}`"
192
192
  class="col span-6 role"
193
193
  >
194
- {{ row.value.roleDisplay }}
194
+ {{ $store.getters['i18n/withFallback'](`customConversion.${row.value.roleDisplay}`, row.value.roleDisplay) }}
195
195
  </div>
196
196
  </div>
197
197
  </template>
@@ -514,7 +514,9 @@ export default {
514
514
  </div>
515
515
 
516
516
  <!-- 自定义插槽,可插入额外内容 -->
517
- <slot name="customize" />
517
+ <div :class=" isDialog? 'namespace-item-row mb-20': 'col span-6'">
518
+ <slot name="customize" />
519
+ </div>
518
520
  <!-- <div
519
521
  v-show="!descriptionHidden"
520
522
  :data-testid="componentTestid + '-description'"
@@ -166,29 +166,44 @@ export default {
166
166
  value: this.purifyOption(role.id),
167
167
  }));
168
168
 
169
- return [
170
- {
171
- label: this.t('projectMembers.projectPermissions.owner.label'),
172
- description: this.t('projectMembers.projectPermissions.owner.description'),
173
- value: 'owner'
174
- },
175
- {
176
- label: this.t('projectMembers.projectPermissions.member.label'),
177
- description: this.t('projectMembers.projectPermissions.member.description'),
178
- value: 'member'
179
- },
180
- {
181
- label: this.t('projectMembers.projectPermissions.readOnly.label'),
182
- description: this.t('projectMembers.projectPermissions.readOnly.description'),
183
- value: 'read-only'
184
- },
185
- ...customRoles,
186
- {
187
- label: this.t('projectMembers.projectPermissions.custom.label'),
188
- description: this.t('projectMembers.projectPermissions.custom.description'),
189
- value: 'custom'
190
- }
191
- ];
169
+ let optionList = [{
170
+ label: this.t('members.clusterPermissions.project-tenant.label'),
171
+ description: this.t('members.clusterPermissions.project-tenant.description'),
172
+ value: 'project-tenant'
173
+ }];
174
+
175
+ if (sessionStorage.getItem('TOPLEVELPERMISSIONS') === 'superadmin') {
176
+ optionList = [
177
+ {
178
+ label: this.t('members.clusterPermissions.project-tenant.label'),
179
+ description: this.t('members.clusterPermissions.project-tenant.description'),
180
+ value: 'project-tenant'
181
+ },
182
+ {
183
+ label: this.t('projectMembers.projectPermissions.owner.label'),
184
+ description: this.t('projectMembers.projectPermissions.owner.description'),
185
+ value: 'owner'
186
+ },
187
+ {
188
+ label: this.t('projectMembers.projectPermissions.member.label'),
189
+ description: this.t('projectMembers.projectPermissions.member.description'),
190
+ value: 'member'
191
+ },
192
+ {
193
+ label: this.t('projectMembers.projectPermissions.readOnly.label'),
194
+ description: this.t('projectMembers.projectPermissions.readOnly.description'),
195
+ value: 'read-only'
196
+ },
197
+ ...customRoles,
198
+ {
199
+ label: this.t('projectMembers.projectPermissions.custom.label'),
200
+ description: this.t('projectMembers.projectPermissions.custom.description'),
201
+ value: 'custom'
202
+ }
203
+ ];
204
+ }
205
+
206
+ return optionList
192
207
  },
193
208
  customPermissionsUpdate() {
194
209
  return this.customPermissions.reduce((acc, customPermissionsItem) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashboard-shell-shell",
3
- "version": "3.0.5-test.46",
3
+ "version": "3.0.5-test.50",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -312,7 +312,7 @@ export default {
312
312
  this.$store.dispatch('auth/setInitialPass', this.password);
313
313
  this.$router.push({ name: 'auth-setup' });
314
314
  } else {
315
- this.$router.push({ name: 'index' });
315
+ this.$router.push({ name: 'home' });
316
316
  }
317
317
 
318
318
  } catch (err) {
@@ -7,6 +7,7 @@ import Loading from '@shell/components/Loading';
7
7
  import { SUBTYPE_MAPPING, CREATE_VERBS } from '@shell/models/management.cattle.io.roletemplate';
8
8
  import { NAME } from '@shell/config/product/auth';
9
9
  import { BLANK_CLUSTER } from '@shell/store/store-types.js';
10
+ import { globalRoleFilteringfn, clusterRoleFilteringfn, projectRoleFilteringfn } from '@shell/utils/roleFiltering'
10
11
 
11
12
  const GLOBAL = SUBTYPE_MAPPING.GLOBAL.key;
12
13
  const CLUSTER = SUBTYPE_MAPPING.CLUSTER.key;
@@ -99,15 +100,38 @@ export default {
99
100
 
100
101
  computed: {
101
102
  globalResources() {
102
- return this.globalRoles;
103
+
104
+ let rolesList = globalRoleFilteringfn(this.globalRoles)
105
+
106
+ if (sessionStorage.getItem('TOPLEVELPERMISSIONS') === 'superadmin') {
107
+ rolesList = this.globalRoles
108
+ }
109
+
110
+ return rolesList
103
111
  },
104
112
 
105
113
  clusterResources() {
106
- return this.roleTemplates.filter((r) => r.context === SUBTYPE_MAPPING.CLUSTER.context);
114
+ const roleList = this.roleTemplates.filter((r) => r.context === SUBTYPE_MAPPING.CLUSTER.context);
115
+
116
+ let rolesList = clusterRoleFilteringfn(roleList)
117
+
118
+ if (sessionStorage.getItem('TOPLEVELPERMISSIONS') === 'superadmin') {
119
+ rolesList = roleList
120
+ }
121
+
122
+ return rolesList
107
123
  },
108
124
 
109
125
  namespaceResources() {
110
- return this.roleTemplates.filter((r) => r.context === SUBTYPE_MAPPING.NAMESPACE.context);
126
+ const roleList = this.roleTemplates.filter((r) => r.context === SUBTYPE_MAPPING.NAMESPACE.context);
127
+
128
+ let rolesList = projectRoleFilteringfn(roleList)
129
+
130
+ if (sessionStorage.getItem('TOPLEVELPERMISSIONS') === 'superadmin') {
131
+ rolesList = roleList
132
+ }
133
+
134
+ return rolesList
111
135
  },
112
136
 
113
137
  type() {
package/pages/home.vue CHANGED
@@ -485,14 +485,6 @@ export default defineComponent({
485
485
  >
486
486
 
487
487
  <!-- 页签标题组件,不显示子页面标题和面包屑 -->
488
- <TabTitle
489
- :show-child="false"
490
- :breadcrumb="false"
491
- >
492
-
493
- <!-- 页面标题:{vendor} - 首页 -->
494
- {{ `${vendor} - ${t('landing.homepage')}` }}
495
- </TabTitle>
496
488
 
497
489
  <!-- 首页欢迎横幅 -->
498
490
  <!-- <BannerGraphic
@@ -509,7 +501,8 @@ export default defineComponent({
509
501
  <div class="row home-panels">
510
502
  <div class="col main-panel">
511
503
  <h2 class="mb-20">
512
- {{ t('landing.clusters.title') }}
504
+ <!-- {{ t('landing.clusters.title') }} -->
505
+ 首页
513
506
  </h2>
514
507
 
515
508
  <!-- 集群列表面板 -->
@@ -668,6 +661,14 @@ export default defineComponent({
668
661
  </button>
669
662
  </template>
670
663
  </PaginatedResourceTable>
664
+ <div v-else class="home-prompt">
665
+ <div style="text-align: center;position: relative;">
666
+ <div class="left-border"></div>
667
+ <!-- <div class="right-border"></div> -->
668
+ <div class="home-prompt-title">欢 迎 登 录</div>
669
+ <div class="home-prompt-subtitle">企业级容器编排与管理解决方案,提供强大的Kubernetes集群管理、应用部署和服务治理能力。</div>
670
+ </div>
671
+ </div>
671
672
  </div>
672
673
 
673
674
  <!-- 单集群模式 -->
@@ -687,6 +688,48 @@ export default defineComponent({
687
688
  </template>
688
689
 
689
690
  <style lang='scss' scoped>
691
+ .home-prompt {
692
+ width: 100%;
693
+ height: 500px;
694
+ display: flex;
695
+ align-items: center;
696
+ justify-content: center;
697
+ .left-border,
698
+ .right-border {
699
+ position: absolute;
700
+ height: 1px;
701
+ width: 120px;
702
+ background: linear-gradient(90deg, transparent, #00a8ff, transparent);
703
+ bottom: 0px;
704
+ }
705
+ .left-border {
706
+ left: calc(50% - 60px);
707
+ }
708
+ .right-border {
709
+ right: 0;
710
+ }
711
+ .home-prompt-title {
712
+ font-size: 32px;
713
+ color: #1a1a1a;
714
+ font-weight: 700;
715
+ letter-spacing: -0.5px;
716
+ margin-bottom: 15px;
717
+ background: linear-gradient(135deg, #00a8ff, #0050b3);
718
+ -webkit-background-clip: text;
719
+ -webkit-text-fill-color: transparent;
720
+ background-clip: text;
721
+ display: inline-block;
722
+ }
723
+
724
+ .home-prompt-subtitle {
725
+ font-size: 18px;
726
+ color: #666666;
727
+ margin-bottom: 20px;
728
+ max-width: 800px;
729
+ margin-left: auto;
730
+ margin-right: auto;
731
+ }
732
+ }
690
733
  .banner-link:focus-visible {
691
734
  @include focus-outline;
692
735
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
3
  # 执行命令示例:
4
- # TAG=shell-pkg-v3.0.5-test.46 ./shell/scripts/publish-shell.sh
4
+ # TAG=shell-pkg-v3.0.5-test.50 ./shell/scripts/publish-shell.sh
5
5
 
6
6
  set -euo pipefail
7
7
 
@@ -4354,6 +4354,14 @@ export function deferred(name: any): {
4354
4354
  export function setPromiseResult(promise: any, obj: any, key: any, label: any): void;
4355
4355
  }
4356
4356
 
4357
+ // @shell/utils/roleFiltering
4358
+
4359
+ declare module '@shell/utils/roleFiltering' {
4360
+ export function globalRoleFilteringfn(ary: any): any;
4361
+ export function clusterRoleFilteringfn(ary: any): any;
4362
+ export function projectRoleFilteringfn(ary: any): any;
4363
+ }
4364
+
4357
4365
  // @shell/utils/router
4358
4366
 
4359
4367
  declare module '@shell/utils/router' {
@@ -0,0 +1,33 @@
1
+ export function globalRoleFilteringfn (ary) {
2
+ const roleList = ['admin', 'tenant', 'safe-admin']
3
+ if (ary && ary.length > 0) {
4
+ return ary.filter(item => { return roleList.includes(item.id) })
5
+ }
6
+ return []
7
+ }
8
+
9
+ export function clusterRoleFilteringfn (ary) {
10
+ const roleList = ['cluster-tenant']
11
+ if (ary && ary.length > 0) {
12
+ ary.map(m => {
13
+ if (m.id === 'cluster-tenant') {
14
+ m['displayName'] = '租户'
15
+ }
16
+ })
17
+ return ary.filter(item => { return roleList.includes(item.id) })
18
+ }
19
+ return []
20
+ }
21
+
22
+ export function projectRoleFilteringfn (ary) {
23
+ const roleList = ['project-tenant']
24
+ ary.map(m => {
25
+ if (m.id === 'project-tenant') {
26
+ m['displayName'] = '租户'
27
+ }
28
+ })
29
+ if (ary && ary.length > 0) {
30
+ return ary.filter(item => { return roleList.includes(item.id) })
31
+ }
32
+ return []
33
+ }