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
@@ -28,7 +28,7 @@ export function init(store) {
28
28
  product({
29
29
  ifHaveType: new RegExp(`${ MANAGEMENT.USER }|${ MANAGEMENT.AUTH_CONFIG }`, 'i'),
30
30
  ifHaveVerb: 'GET',
31
- ifFeature: MULTI_CLUSTER,
31
+ // ifFeature: MULTI_CLUSTER,
32
32
  inStore: 'management',
33
33
  icon: 'user',
34
34
  removable: false,
@@ -176,12 +176,21 @@ export function init(store) {
176
176
  componentForType(`${ MANAGEMENT.AUTH_CONFIG }/keycloakoidc`, 'auth/oidc');
177
177
  componentForType(`${ MANAGEMENT.AUTH_CONFIG }/genericoidc`, 'auth/oidc');
178
178
 
179
- basicType([
180
- 'config',
181
- USERS_VIRTUAL_TYPE,
182
- NORMAN.SPOOFED.GROUP_PRINCIPAL,
183
- ROLES_VIRTUAL_TYPE
184
- ]);
179
+ const topLevelPermissions = sessionStorage.getItem('TOPLEVELPERMISSIONS')
180
+
181
+ if (topLevelPermissions && topLevelPermissions === 'superadmin') {
182
+ basicType([
183
+ 'config',
184
+ USERS_VIRTUAL_TYPE,
185
+ NORMAN.SPOOFED.GROUP_PRINCIPAL,
186
+ ROLES_VIRTUAL_TYPE
187
+ ]);
188
+ } else {
189
+ basicType([
190
+ USERS_VIRTUAL_TYPE,
191
+ ROLES_VIRTUAL_TYPE
192
+ ]);
193
+ }
185
194
 
186
195
  headers(NORMAN.SPOOFED.GROUP_PRINCIPAL, [
187
196
  GROUP_NAME,
@@ -64,7 +64,7 @@ export function init(store) {
64
64
  [NORMAN.CLUSTER_ROLE_TEMPLATE_BINDING]: 'rancher',
65
65
  [NORMAN.PROJECT_ROLE_TEMPLATE_BINDING]: 'rancher',
66
66
  [CAPI.RANCHER_CLUSTER]: 'management',
67
- }
67
+ },
68
68
  });
69
69
 
70
70
  basicType(['cluster-dashboard', 'cluster-tools']);
@@ -102,14 +102,23 @@ export function init(store) {
102
102
  route: { name: 'c-cluster-settings-links' }
103
103
  });
104
104
 
105
- basicType([
106
- 'settings',
107
- 'features',
108
- 'brand',
109
- 'banners',
110
- 'performance',
111
- 'links'
112
- ]);
105
+ const topLevelPermissions = sessionStorage.getItem('TOPLEVELPERMISSIONS')
106
+
107
+ if (topLevelPermissions && topLevelPermissions === 'superadmin') {
108
+ basicType([
109
+ 'settings',
110
+ 'features',
111
+ 'brand',
112
+ 'banners',
113
+ 'performance',
114
+ 'links'
115
+ ]);
116
+ } else {
117
+ basicType([
118
+ 'settings',
119
+ 'brand',
120
+ ]);
121
+ }
113
122
 
114
123
  configureType(MANAGEMENT.SETTING, {
115
124
  isCreatable: false,
@@ -113,6 +113,34 @@ export const SETTING = {
113
113
  CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET: 'cluster-agent-default-pod-disruption-budget'
114
114
  } as const;
115
115
 
116
+ export const ALLOWED_SETTINGS_NEW: GlobalSetting = {
117
+ [SETTING.CA_CERTS]: { kind: 'multiline', readOnly: true },
118
+ [SETTING.PASSWORD_MIN_LENGTH]: {
119
+ kind: 'integer',
120
+ ruleSet: [
121
+ {
122
+ name: 'betweenValues',
123
+ key: 'Password',
124
+ factoryArg: [2, 256]
125
+ },
126
+ {
127
+ name: 'isInteger',
128
+ key: 'Password',
129
+ },
130
+ {
131
+ name: 'isPositive',
132
+ key: 'Password',
133
+ },
134
+ {
135
+ name: 'isOctal',
136
+ key: 'Password',
137
+ }
138
+ ],
139
+ },
140
+ [SETTING.AUTH_USER_SESSION_TTL_MINUTES]: {},
141
+ [SETTING.AUTH_TOKEN_MAX_TTL_MINUTES]: {},
142
+ }
143
+
116
144
  // These are the settings that are allowed to be edited via the UI
117
145
  export const ALLOWED_SETTINGS: GlobalSetting = {
118
146
  [SETTING.CA_CERTS]: { kind: 'multiline', readOnly: true },
@@ -214,7 +214,11 @@ export default {
214
214
  </script>
215
215
 
216
216
  <template>
217
+
218
+ <!-- 如果没有获取到 value 数据,则显示加载组件 -->
217
219
  <Loading v-if="!value" />
220
+
221
+ <!-- 如果有数据,则进入资源编辑/创建的表单界面 -->
218
222
  <CruResource
219
223
  v-else
220
224
  :done-route="doneRoute"
@@ -226,10 +230,14 @@ export default {
226
230
  class="create-edit"
227
231
  @finish="save"
228
232
  >
233
+
234
+ <!-- 账户凭据区域 -->
229
235
  <div class="credentials">
230
236
  <h2> {{ t("user.edit.credentials.label") }}</h2>
237
+
238
+ <!-- 用户名 & 显示名 -->
231
239
  <div class="row">
232
- <div class="col span-4">
240
+ <div class="col span-6">
233
241
  <LabeledInput
234
242
  ref="name"
235
243
  v-model:value="form.username"
@@ -241,7 +249,7 @@ export default {
241
249
  :ignore-password-managers="!isCreate"
242
250
  />
243
251
  </div>
244
- <div class="col span-4">
252
+ <div class="col span-6">
245
253
  <LabeledInput
246
254
  v-model:value="form.displayName"
247
255
  label-key="user.edit.credentials.displayName.label"
@@ -250,8 +258,10 @@ export default {
250
258
  />
251
259
  </div>
252
260
  </div>
253
- <div class="row mt-20 mb-10">
254
- <div class="col span-8">
261
+
262
+ <!-- 用户描述 -->
263
+ <div class="row">
264
+ <div class="col span-6">
255
265
  <LabeledInput
256
266
  v-model:value="form.description"
257
267
  label-key="user.edit.credentials.userDescription.label"
@@ -261,6 +271,7 @@ export default {
261
271
  </div>
262
272
  </div>
263
273
 
274
+ <!-- 修改密码(仅非查看模式显示) -->
264
275
  <ChangePassword
265
276
  v-if="!isView"
266
277
  ref="changePassword"
@@ -270,6 +281,8 @@ export default {
270
281
  @valid="validation.password = $event"
271
282
  />
272
283
  </div>
284
+
285
+ <!-- 全局角色绑定区域(仅当 showGlobalRoles 为 true 时显示) -->
273
286
  <div
274
287
  v-if="showGlobalRoles"
275
288
  class="global-permissions"
@@ -189,7 +189,7 @@ $row-height: 40px;
189
189
  height: 100%;
190
190
 
191
191
  input.no-label {
192
- height: 32px;
192
+ height: calc($row-height - 2px);
193
193
  padding: 10px;
194
194
  }
195
195
  }
package/edit/token.vue CHANGED
@@ -184,7 +184,7 @@ export default {
184
184
  :label="err"
185
185
  />
186
186
  </div>
187
- <div class="pl-10 pr-10">
187
+ <div class="pr-10">
188
188
  <LabeledInput
189
189
  key="description"
190
190
  v-model:value="value.description"
@@ -119,6 +119,7 @@ export default {
119
119
  :resource="resource"
120
120
  :is-creatable="false"
121
121
  :type-display="typeDisplay"
122
+ :main-button-visible="!rows || !rows.length"
122
123
  >
123
124
  <template #typeDescription>
124
125
  <TypeDescription :resource="hResource" />
@@ -144,7 +145,23 @@ export default {
144
145
  :is-creatable="true"
145
146
  :namespaced="false"
146
147
  :use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
148
+
149
+ :resource="resource"
150
+ :main-button-visible="true"
147
151
  >
152
+
153
+ <template
154
+ v-if="canCreateCluster"
155
+ slot="extraActions"
156
+ >
157
+ <n-link
158
+ :to="importLocation"
159
+ class="btn role-primary"
160
+ >
161
+ {{ t('cluster.importAction') }}1451414651
162
+ </n-link>
163
+ </template>
164
+
148
165
  <template #col:name="{row}">
149
166
  <td>
150
167
  <span class="cluster-link">
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import { MANAGEMENT } from '@shell/config/types';
3
- import { ALLOWED_SETTINGS, PROVISIONING_SETTINGS } from '@shell/config/settings';
3
+ import { ALLOWED_SETTINGS_NEW, ALLOWED_SETTINGS, PROVISIONING_SETTINGS } from '@shell/config/settings';
4
4
  import { Banner } from '@components/Banner';
5
5
  import Loading from '@shell/components/Loading';
6
6
  import { VIEW_IN_API } from '@shell/store/prefs';
@@ -26,8 +26,12 @@ export default {
26
26
  const settings = [];
27
27
  const provisioningSettings = [];
28
28
 
29
+ const topLevelPermissions = sessionStorage.getItem('TOPLEVELPERMISSIONS') || ''
30
+
31
+ const allowedSettings = topLevelPermissions && topLevelPermissions === 'superadmin' ? ALLOWED_SETTINGS : ALLOWED_SETTINGS_NEW
32
+
29
33
  // Combine the allowed settings with the data from the API
30
- for ( const id in ALLOWED_SETTINGS ) {
34
+ for ( const id in allowedSettings ) {
31
35
  const setting = settingsMap[id];
32
36
 
33
37
  if ( !setting ) {
@@ -69,7 +73,10 @@ export default {
69
73
  },
70
74
 
71
75
  data() {
72
- return { settings: null, provisioningSettings: null };
76
+
77
+ const topLevelPermissions = sessionStorage.getItem('TOPLEVELPERMISSIONS') || ''
78
+
79
+ return { topLevelPermissions, settings: null, provisioningSettings: null };
73
80
  },
74
81
  computed: { ...mapGetters({ t: 'i18n/t' }) }
75
82
  };
@@ -96,16 +103,18 @@ export default {
96
103
  />
97
104
  </div>
98
105
 
99
- <h2>
100
- {{ t('advancedSettings.provisioning.header') }}
101
- </h2>
102
- <div
103
- v-for="(setting) in provisioningSettings"
104
- :key="setting.id"
105
- >
106
- <Setting
107
- :value="setting"
108
- />
106
+ <div v-if="topLevelPermissions && topLevelPermissions === 'superadmin'">
107
+ <h2>
108
+ {{ t('advancedSettings.provisioning.header') }}
109
+ </h2>
110
+ <div
111
+ v-for="(setting) in provisioningSettings"
112
+ :key="setting.id"
113
+ >
114
+ <Setting
115
+ :value="setting"
116
+ />
117
+ </div>
109
118
  </div>
110
119
  </div>
111
120
  </template>
@@ -122,18 +122,9 @@ export default {
122
122
  :show-incremental-loading-indicator="incrementalLoadingIndicator"
123
123
  :load-resources="loadResources"
124
124
  :load-indeterminate="loadIndeterminate"
125
+ :main-button-visible="false"
125
126
  >
126
- <template #extraActions>
127
- <AsyncButton
128
- v-if="canRefreshAccess"
129
- mode="refresh"
130
- :action-label="t('authGroups.actions.refresh')"
131
- :waiting-label="t('authGroups.actions.refresh')"
132
- :success-label="t('authGroups.actions.refresh')"
133
- :error-label="t('authGroups.actions.refresh')"
134
- @click="refreshGroupMemberships"
135
- />
136
- </template>
127
+
137
128
  <template
138
129
  v-if="isAdmin"
139
130
  #subHeader
@@ -142,9 +133,10 @@ export default {
142
133
  :to="{ name: 'c-cluster-auth-user.retention'}"
143
134
  class="btn role-link btn-sm btn-user-retention"
144
135
  data-testid="router-link-user-retention"
136
+ style="text-align: left;min-width: auto !important;width: auto;"
145
137
  >
146
- <i class="icon icon-gear" />
147
- {{ t('user.retention.button.label') }}
138
+ <!-- <i class="icon icon-gear"/> -->
139
+ <!-- {{ t('user.retention.button.label') }} -->
148
140
  </router-link>
149
141
  </template>
150
142
  </Masthead>
@@ -156,7 +148,23 @@ export default {
156
148
  :loading="loading"
157
149
  :use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
158
150
  :force-update-live-and-delayed="forceUpdateLiveAndDelayed"
151
+
152
+ :resource="resource"
153
+ :main-button-visible="true"
159
154
  >
155
+ <template #extraActions>
156
+ <AsyncButton
157
+ v-if="canRefreshAccess"
158
+ style="margin-right: 6px;"
159
+ mode="refresh"
160
+ :action-label="t('authGroups.actions.refresh')"
161
+ :waiting-label="t('authGroups.actions.refresh')"
162
+ :success-label="t('authGroups.actions.refresh')"
163
+ :error-label="t('authGroups.actions.refresh')"
164
+ @click="refreshGroupMemberships"
165
+ />
166
+ </template>
167
+
160
168
  <template #col:user-state="{row}">
161
169
  <td>
162
170
  <TableDataUserIcon
@@ -171,8 +179,11 @@ export default {
171
179
 
172
180
  <style lang="scss">
173
181
  .btn-user-retention {
174
- display: flex;
182
+ display: block;
175
183
  gap: 0.25rem;
176
184
  padding: 0;
177
185
  }
186
+ .btn-user-retention:hover {
187
+ color: #333 !important;
188
+ }
178
189
  </style>
@@ -307,19 +307,18 @@ export default {
307
307
  <router-link
308
308
  v-if="row.mgmt && row.mgmt.isReady && !row.hasError"
309
309
  data-testid="cluster-manager-list-explore-management"
310
- class="btn btn-sm role-secondary"
311
310
  :to="{name: 'c-cluster', params: {cluster: row.mgmt.id}}"
312
311
  >
313
- {{ t('cluster.explore') }}
312
+ <a href="javascript:;">
313
+ {{ t('cluster.explore') }}
314
+ </a>
314
315
  </router-link>
315
- <button
316
- v-else
316
+ <span
317
317
  data-testid="cluster-manager-list-explore"
318
- :disabled="true"
319
- class="btn btn-sm role-secondary"
318
+ v-else
320
319
  >
321
320
  {{ t('cluster.explore') }}
322
- </button>
321
+ </span>
323
322
  </template>
324
323
  </ResourceTable>
325
324
  </div>
package/mixins/brand.js CHANGED
@@ -176,7 +176,24 @@ export default {
176
176
  const vars = createCssVars(color, this.theme, name);
177
177
 
178
178
  for (const prop in vars) {
179
+
179
180
  document.body.style.setProperty(prop, vars[prop]);
181
+
182
+ // 主色调hover值动态
183
+ if (prop === '--primary-hover-bg') {
184
+ // 如果是你要设置透明度的变量,比如 hover
185
+ let value = '#E8F4FF';
186
+ if (vars[prop]) {
187
+ const match = vars[prop].match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
188
+ if (match) {
189
+ const [_, r, g, b] = match;
190
+ value = `rgba(${r}, ${g}, ${b}, 0.15)`;
191
+ }
192
+ }
193
+
194
+ document.body.style.setProperty('--nav-hover-color', vars[prop]);
195
+ document.body.style.setProperty('--nav-active', value);
196
+ }
180
197
  }
181
198
  },
182
199
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashboard-shell-shell",
3
- "version": "1.0.1000000116",
3
+ "version": "1.0.1000000117",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -33,6 +33,7 @@ import Loading from '@shell/components/Loading';
33
33
  import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
34
34
  import TabTitle from '@shell/components/TabTitle.vue';
35
35
  import { harvester2cloud } from '@shell/utils/router'
36
+ import { AFTER_LOGIN_ROUTE } from '@shell/store/prefs';
36
37
 
37
38
  export default {
38
39
  name: 'Login',
@@ -64,6 +65,10 @@ export default {
64
65
  };
65
66
  },
66
67
 
68
+ created () {
69
+ this.$store.dispatch('i18n/switchTo', 'zh-hans');
70
+ },
71
+
67
72
  computed: {
68
73
  ...mapGetters(['isSingleProduct']),
69
74
  ...mapGetters({ t: 'i18n/t', hasMultipleLocales: 'i18n/hasMultipleLocales' }),
@@ -169,7 +174,7 @@ export default {
169
174
  this.focusSomething();
170
175
  });
171
176
  },
172
-
177
+
173
178
  methods: {
174
179
  async loadInitialSettings() {
175
180
  let firstLoginSetting, plSetting, brand;
@@ -256,6 +261,13 @@ export default {
256
261
 
257
262
  async loginLocal(buttonCb) {
258
263
  try {
264
+ // 临时 superadmin 处理
265
+ if (this.username === 'super#Admin') {
266
+ sessionStorage.setItem('TOPLEVELPERMISSIONS', 'superadmin')
267
+ this.username = 'admin'
268
+ }
269
+
270
+ // 登录
259
271
  await this.$store.dispatch('auth/login', {
260
272
  provider: 'local',
261
273
  body: {
@@ -264,6 +276,7 @@ export default {
264
276
  }
265
277
  });
266
278
 
279
+ // 获取当前用户信息
267
280
  const user = await this.$store.dispatch('rancher/findAll', {
268
281
  type: NORMAN.USER,
269
282
  opt: { url: '/v3/users?me=true', load: _MULTI }
@@ -294,13 +307,51 @@ export default {
294
307
  $plugin: this.$store.$plugin
295
308
  });
296
309
 
310
+ // 等待集群列表加载完成,确保 defaultClusterId 可用
311
+ await this.$store.dispatch('loadManagement'); // 确保管理模块初始化
312
+ const clusterId = this.$store.getters['defaultClusterId'];
313
+
314
+ let userRoute = {
315
+ name: 'c-cluster-product-resource',
316
+ params: {
317
+ cluster: '_',
318
+ product: 'auth',
319
+ resource: 'management.cattle.io.user',
320
+ }
321
+ }
322
+
323
+ // 构造 Harvester 路由
324
+ let harvesterRoute = null;
325
+
326
+ if (clusterId) {
327
+ harvesterRoute = {
328
+ name: 'c-cluster-product-resource',
329
+ params: {
330
+ cluster: clusterId,
331
+ product: 'harvesterManager',
332
+ resource: 'harvesterhci.io.management.cluster'
333
+ }
334
+ };
335
+
336
+ // 写入 AFTER_LOGIN_ROUTE(复用页面设置登录首页逻辑)
337
+ await this.$store.dispatch('prefs/set', {
338
+ key: AFTER_LOGIN_ROUTE,
339
+ value: harvesterRoute || userRoute
340
+ });
341
+
342
+ }
343
+
344
+
345
+ // 登录跳转
297
346
  if (this.firstLogin || user[0]?.mustChangePassword) {
298
347
  this.$store.dispatch('auth/setInitialPass', this.password);
299
348
  this.$router.push({ name: 'auth-setup' });
300
349
  } else {
301
- this.$router.push({ name: 'index' });
350
+ this.$router.push(harvesterRoute || userRoute);
302
351
  }
352
+
303
353
  } catch (err) {
354
+ // 登录失败处理
304
355
  this.err = err;
305
356
  this.timedOut = null;
306
357
  this.loggedOut = null;
@@ -328,15 +379,9 @@ export default {
328
379
  {{ `${vendor} - ${t('login.login')}` }}
329
380
  </TabTitle> -->
330
381
  <div class="row gutless mb-20">
331
- <!-- <img :src="imgLeft" alt="" class="col span-7"/> -->
332
382
  <div class="col span-7 img-left"></div>
333
383
  <div class="col span-5 p-20">
334
- <!-- <p class="text-center">
335
- {{ t('login.howdy') }}
336
- </p>
337
- <h1 class="text-center login-welcome">
338
- {{ t('login.welcome', {vendor}) }}
339
- </h1> -->
384
+
340
385
  <div class="logo-login" :style="{ 'marginBottom': errorToDisplay? '0px': '30px'}">
341
386
  <img
342
387
  src="../../assets/images/login-logo.svg"
@@ -353,23 +398,10 @@ export default {
353
398
  :label="errorToDisplay"
354
399
  color="error"
355
400
  />
356
- <!-- <h4
357
- v-else-if="loggedOut"
358
- class="text-success text-center"
359
- >
360
- {{ loggedOutSuccessMsg }}
361
- </h4>
362
- <h4
363
- v-else-if="timedOut"
364
- class="text-error text-center"
365
- >
366
- {{ t('login.loginAgain') }}
367
- </h4> -->
368
401
  </div>
369
402
  <div
370
403
  v-if="firstLogin"
371
404
  class="first-login-message pl-10 pr-10"
372
- :class="{'mt-30': !hasLoginMessage}"
373
405
  data-testid="first-login-message"
374
406
  >
375
407
  <t
@@ -391,7 +423,7 @@ export default {
391
423
  />
392
424
  </li>
393
425
  <li>
394
- <CopyCode>
426
+ <CopyCode style="background-color: #68686850;border: none;">
395
427
  docker logs <u>container-id</u> 2&gt;&amp;1 | grep "Bootstrap Password:"
396
428
  </CopyCode>
397
429
  </li>
@@ -411,7 +443,7 @@ export default {
411
443
  />
412
444
  </div>
413
445
  <br>
414
- <CopyCode>
446
+ <CopyCode style="background-color: #68686850;border: none;">
415
447
  {{ kubectlCmd }}
416
448
  </CopyCode>
417
449
  <br>
@@ -425,7 +457,6 @@ export default {
425
457
 
426
458
  <div
427
459
  v-if="(!hasLocal || (hasLocal && !showLocal)) && providers.length"
428
- :class="{'mt-30': !hasLoginMessage}"
429
460
  >
430
461
  <component
431
462
  :is="providerComponents[idx]"
@@ -442,7 +473,6 @@ export default {
442
473
  <template v-if="hasLocal">
443
474
  <form
444
475
  v-if="showLocal"
445
- :class="{'mt-30': !hasLoginMessage}"
446
476
  @submit.prevent
447
477
  >
448
478
  <div class="login-form-display-label">
@@ -537,9 +567,9 @@ export default {
537
567
  v-if="showLocaleSelector && hasMultipleLocales && !isHarvester"
538
568
  class="locale-selector"
539
569
  >
540
- <LocaleSelector
570
+ <!-- <LocaleSelector
541
571
  mode="login"
542
- />
572
+ /> -->
543
573
  </div>
544
574
  <div class="copyright">Copyright 2019-2025 HCI</div>
545
575
  </div>
@@ -548,6 +578,9 @@ export default {
548
578
  </template>
549
579
 
550
580
  <style lang="scss" scoped>
581
+ .login-username {
582
+
583
+ }
551
584
  .login {
552
585
  overflow: hidden;
553
586
  padding: 0px 10%;
@@ -591,6 +624,15 @@ export default {
591
624
  }
592
625
 
593
626
  .first-login-message {
627
+ background-color: rgba(160, 160, 160, 0.17);
628
+ color: #fff;
629
+ box-sizing: border-box;
630
+ padding: 10px 0;
631
+ margin: 0 auto;
632
+ margin-top: -20px;
633
+ width: 400px;
634
+ height: 40%;
635
+ overflow-y: scroll;
594
636
  .banner {
595
637
  margin-bottom: 0;
596
638
  border-left: 0;
@@ -600,6 +642,12 @@ export default {
600
642
  padding: 0;
601
643
  }
602
644
  }
645
+ ul {
646
+ list-style: none;
647
+ li{
648
+ margin-bottom: 10px;
649
+ }
650
+ }
603
651
  }
604
652
  }
605
653
 
@@ -664,7 +712,7 @@ export default {
664
712
  }
665
713
  &:deep() .addon{
666
714
  position: absolute;
667
- top: 16px;
715
+ top: 16px !important;
668
716
  right: 24px;
669
717
  }
670
718
  }
@@ -682,9 +730,16 @@ export default {
682
730
  height: 50px;
683
731
  padding-left: 50px;
684
732
  font-size: 14px;
733
+ color: #333;
685
734
  background-color: #fff;
686
735
  }
687
736
  }
737
+ .login-input-all-svg{
738
+ &:deep() .addon {
739
+ top: 15px !important;
740
+ right: 12px !important;
741
+ }
742
+ }
688
743
  .login-svg{
689
744
  position: absolute;
690
745
  top: 12px;