dashboard-shell-shell 3.0.2-rc.105 → 3.0.2-test.20250913
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.
- package/components/SortableTable/index.vue +4 -3
- package/components/form/KeyValue.vue +2 -15
- package/components/form/MatchExpressions.vue +2 -2
- package/components/form/NameNsDescription.vue +1 -1
- package/components/nav/NamespaceFilter.vue +2 -2
- package/config/router/navigation-guards/index.js +15 -7
- package/config/table-headers.js +1 -1
- package/package.json +1 -1
- package/pages/auth/login.vue +1 -35
- package/store/type-map.js +1 -2
- package/utils/error.js +4 -0
- package/utils/router.js +4 -4
|
@@ -417,7 +417,7 @@ export default {
|
|
|
417
417
|
const isLoading = this.loading || false;
|
|
418
418
|
|
|
419
419
|
let isCreatable = false;
|
|
420
|
-
const lastPath = this.$route
|
|
420
|
+
const lastPath = this.$route?.path.split('/').pop();
|
|
421
421
|
|
|
422
422
|
if (lastPath.includes('.')) {
|
|
423
423
|
isCreatable = this.$store.getters['type-map/optionsFor'](lastPath).isCreatable;
|
|
@@ -1753,10 +1753,11 @@ export default {
|
|
|
1753
1753
|
@mouseover="setBulkActionOfInterest(act)"
|
|
1754
1754
|
@mouseleave="setBulkActionOfInterest(null)"
|
|
1755
1755
|
>
|
|
1756
|
-
<i
|
|
1756
|
+
<!-- <i
|
|
1757
1757
|
v-if="act.icon"
|
|
1758
1758
|
:class="act.icon"
|
|
1759
|
-
|
|
1759
|
+
style="line-height: 12px;height: 12px;font-size: 12px;"
|
|
1760
|
+
/> -->
|
|
1760
1761
|
<span v-clean-html="act.label" />
|
|
1761
1762
|
</button>
|
|
1762
1763
|
<template v-if="featureDropdownMenu">
|
|
@@ -388,17 +388,6 @@ export default {
|
|
|
388
388
|
});
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
rows = rows.map((item) => {
|
|
392
|
-
if (item.key && item.key.includes('harvester')) {
|
|
393
|
-
item.key = item.key.replace('harvester', 'cloud');
|
|
394
|
-
}
|
|
395
|
-
if (item.key && item.value.includes('harvester')) {
|
|
396
|
-
item.value = item.value.replace('harvester', 'cloud');
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return item;
|
|
400
|
-
});
|
|
401
|
-
|
|
402
391
|
return rows;
|
|
403
392
|
},
|
|
404
393
|
|
|
@@ -409,8 +398,6 @@ export default {
|
|
|
409
398
|
[this.valueName]: value,
|
|
410
399
|
};
|
|
411
400
|
|
|
412
|
-
obj.key = obj.key?.replace('harvester', 'cloud');
|
|
413
|
-
obj.value = obj.value?.replace('harvester', 'cloud');
|
|
414
401
|
obj.binary = false;
|
|
415
402
|
obj.canEncode = this.handleBase64;
|
|
416
403
|
obj.supported = true;
|
|
@@ -492,8 +479,8 @@ export default {
|
|
|
492
479
|
// let value = (row[valueName] || '');
|
|
493
480
|
// const key = (row[keyName] || '').trim();
|
|
494
481
|
|
|
495
|
-
const key = (row[keyName]
|
|
496
|
-
let value = (row[valueName]
|
|
482
|
+
const key = (row[keyName] || '').trim();
|
|
483
|
+
let value = (row[valueName] || '').trim();
|
|
497
484
|
|
|
498
485
|
if (value && typeOf(value) === 'object') {
|
|
499
486
|
out[key] = JSON.parse(JSON.stringify(value));
|
|
@@ -289,7 +289,7 @@ export default {
|
|
|
289
289
|
:data-testid="`input-match-type-field-${index}`"
|
|
290
290
|
>
|
|
291
291
|
<div v-if="isView">
|
|
292
|
-
{{ row.matching
|
|
292
|
+
{{ row.matching }}
|
|
293
293
|
<!-- {{ row.matching }} -->
|
|
294
294
|
</div>
|
|
295
295
|
<LabeledSelect
|
|
@@ -305,7 +305,7 @@ export default {
|
|
|
305
305
|
:data-testid="`input-match-expression-key-${index}`"
|
|
306
306
|
>
|
|
307
307
|
<div v-if="isView" class="view-item-value">
|
|
308
|
-
{{ row.key
|
|
308
|
+
{{ row.key }}
|
|
309
309
|
</div>
|
|
310
310
|
<input
|
|
311
311
|
v-else-if="!hasKeySelectOptions"
|
|
@@ -252,7 +252,7 @@ export default {
|
|
|
252
252
|
const options = namespaces
|
|
253
253
|
.map((namespace) => ({ nameDisplay: namespace, id: namespace }))
|
|
254
254
|
.map(props.namespaceMapper || ((obj) => ({
|
|
255
|
-
label: obj.nameDisplay
|
|
255
|
+
label: obj.nameDisplay,
|
|
256
256
|
value: obj.id,
|
|
257
257
|
})));
|
|
258
258
|
|
|
@@ -753,7 +753,7 @@ export default {
|
|
|
753
753
|
:data-testid="`namespaces-value-${j}`"
|
|
754
754
|
class="ns-value"
|
|
755
755
|
>
|
|
756
|
-
<div>{{ ns.label
|
|
756
|
+
<div>{{ ns.label }}</div>
|
|
757
757
|
<!-- block user from removing the last selection if ns forced filtering is on -->
|
|
758
758
|
<i
|
|
759
759
|
v-if="!namespaceFilterMode || value.length > 1"
|
|
@@ -864,7 +864,7 @@ export default {
|
|
|
864
864
|
v-if="opt.kind === NAMESPACE_FILTER_KINDS.NAMESPACE"
|
|
865
865
|
class="icon icon-folder"
|
|
866
866
|
/>
|
|
867
|
-
<div>{{ opt.label
|
|
867
|
+
<div>{{ opt.label }}</div>
|
|
868
868
|
<i
|
|
869
869
|
v-if="opt.selected"
|
|
870
870
|
class="icon icon-checkmark"
|
|
@@ -22,17 +22,17 @@ export function installNavigationGuards(router, context) {
|
|
|
22
22
|
let changed = false;
|
|
23
23
|
const params = { ...to.params };
|
|
24
24
|
|
|
25
|
-
if (params
|
|
25
|
+
if (params?.product?.includes('cloud')) {
|
|
26
26
|
params.product = params.product.replace(/cloud/g, 'harvester');
|
|
27
27
|
changed = true;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
if (params
|
|
30
|
+
if (params?.cluster?.includes('cloud')) {
|
|
31
31
|
params.cluster = params.cluster.replace(/cloud/g, 'harvester');
|
|
32
32
|
changed = true;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
if (params
|
|
35
|
+
if (params?.resource?.includes('cloud')) {
|
|
36
36
|
params.resource = params.resource.replace(/cloud/g, 'harvester');
|
|
37
37
|
changed = true;
|
|
38
38
|
}
|
|
@@ -64,14 +64,22 @@ export function installNavigationGuards(router, context) {
|
|
|
64
64
|
|
|
65
65
|
// 🔹 最后执行:只改地址栏,不改内部
|
|
66
66
|
router.afterEach((to) => {
|
|
67
|
+
const base = router.options.history?.base || ''; // 获取 router base,防止丢失
|
|
68
|
+
let cloudPath = to.fullPath.replace(/harvester/g, 'cloud');
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
// fullPath 可能已经不带 base,需要拼回去
|
|
71
|
+
if (!cloudPath.startsWith(base)) {
|
|
72
|
+
cloudPath = base + cloudPath;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 获取当前地址栏完整 URL(path + search + hash)
|
|
76
|
+
const currentLocation = window.location.pathname + window.location.search + window.location.hash;
|
|
70
77
|
|
|
71
|
-
|
|
78
|
+
// 只有在地址栏实际不同的时候才替换,避免死循环
|
|
79
|
+
if (cloudPath !== currentLocation) {
|
|
80
|
+
console.info('[URL Replace] Updating address bar:', currentLocation, '→', cloudPath);
|
|
72
81
|
window.history.replaceState({}, '', cloudPath);
|
|
73
82
|
}
|
|
74
|
-
|
|
75
83
|
});
|
|
76
84
|
}
|
|
77
85
|
|
package/config/table-headers.js
CHANGED
|
@@ -162,7 +162,7 @@ export const NAMESPACE = {
|
|
|
162
162
|
name: 'namespace',
|
|
163
163
|
labelKey: 'tableHeaders.namespace',
|
|
164
164
|
value: 'namespace',
|
|
165
|
-
getValue: row => row && row.namespace && row.namespace
|
|
165
|
+
getValue: row => row && row.namespace && row.namespace,
|
|
166
166
|
sort: 'namespace',
|
|
167
167
|
dashIfEmpty: true,
|
|
168
168
|
};
|
package/package.json
CHANGED
package/pages/auth/login.vue
CHANGED
|
@@ -307,47 +307,13 @@ export default {
|
|
|
307
307
|
$plugin: this.$store.$plugin
|
|
308
308
|
});
|
|
309
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
310
|
|
|
345
311
|
// 登录跳转
|
|
346
312
|
if (this.firstLogin || user[0]?.mustChangePassword) {
|
|
347
313
|
this.$store.dispatch('auth/setInitialPass', this.password);
|
|
348
314
|
this.$router.push({ name: 'auth-setup' });
|
|
349
315
|
} else {
|
|
350
|
-
this.$router.push(
|
|
316
|
+
this.$router.push({ name: 'index' });
|
|
351
317
|
}
|
|
352
318
|
|
|
353
319
|
} catch (err) {
|
package/store/type-map.js
CHANGED
|
@@ -513,7 +513,7 @@ export const getters = {
|
|
|
513
513
|
|
|
514
514
|
groupsForVirTypes(state) {
|
|
515
515
|
return (product, name) => {
|
|
516
|
-
return state.virtualTypes?.[product]
|
|
516
|
+
return state.virtualTypes?.[product].find(item => item.name === name)?.icon;
|
|
517
517
|
};
|
|
518
518
|
},
|
|
519
519
|
|
|
@@ -718,7 +718,6 @@ export const getters = {
|
|
|
718
718
|
route.params = route.params || {};
|
|
719
719
|
route.params.cluster = clusterId;
|
|
720
720
|
route.params.product = productId;
|
|
721
|
-
route.params.resource = route.params.resource;
|
|
722
721
|
}
|
|
723
722
|
|
|
724
723
|
group.children.push({
|
package/utils/error.js
CHANGED
|
@@ -138,6 +138,10 @@ export const normalizeError = (err) => {
|
|
|
138
138
|
};
|
|
139
139
|
};
|
|
140
140
|
export function translateError(error) {
|
|
141
|
+
error = typeof error === 'string'
|
|
142
|
+
? error
|
|
143
|
+
: error?.message || error?.toString() || '';
|
|
144
|
+
|
|
141
145
|
const originError = error;
|
|
142
146
|
error = error?.toLowerCase().replace(/admission webhook(.*?)denied the request:/g, (match, p1) => {
|
|
143
147
|
return '';
|
package/utils/router.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { INSTALL_REDIRECT_META_KEY } from '@shell/config/router/navigation-guards/install-redirect';
|
|
2
2
|
|
|
3
3
|
export function harvesterhci2cloud(str) {
|
|
4
|
-
|
|
4
|
+
return str?.replace('harvesterhci.io', 'cloudhci.io')
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export function cloud2harvesterhci(str) {
|
|
@@ -14,11 +14,11 @@ export function cloud2harvesterhci(str) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function harvester2cloud(str) {
|
|
17
|
-
|
|
17
|
+
return str?.replace('harvester', 'cloud')
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export function cloud2harvester(str) {
|
|
21
|
-
|
|
21
|
+
return str?.replace('cloud', 'harvester')
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function queryParamsFor(current, qp, defaults = {}) {
|
|
@@ -89,7 +89,7 @@ export const getPackageFromRoute = (route) => {
|
|
|
89
89
|
};
|
|
90
90
|
|
|
91
91
|
export const getResourceFromRoute = (to) => {
|
|
92
|
-
let resource =
|
|
92
|
+
let resource = to.params?.resource;
|
|
93
93
|
|
|
94
94
|
if (!resource) {
|
|
95
95
|
resource = findMeta(to, 'resource');
|