dashboard-shell-shell 3.0.5-logtest.2 → 3.0.5-order.1

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 (37) hide show
  1. package/assets/images/arrow.svg +1 -0
  2. package/assets/images/headerIcon/auth.svg +1 -0
  3. package/assets/images/headerIcon/settings.svg +1 -0
  4. package/assets/images/home.svg +6 -0
  5. package/assets/images/pl/logo.png +0 -0
  6. package/assets/styles/global/_layout.scss +2 -2
  7. package/assets/styles/global/_tooltip.scss +3 -1
  8. package/assets/translations/en-us.yaml +1 -0
  9. package/assets/translations/zh-hans.yaml +41 -36
  10. package/components/HoverDropdown.vue +0 -0
  11. package/components/ResourceList/Masthead.vue +8 -1
  12. package/components/form/NameNsDescription.vue +15 -0
  13. package/components/nav/Header copy.vue +1157 -0
  14. package/components/nav/Header.vue +70 -59
  15. package/components/nav/TopLevelMenu.vue +0 -1
  16. package/components/nav/TopLevelMenuNew.vue +607 -0
  17. package/components/nav/configurationApps.vue +102 -0
  18. package/components/nav/menuDropdown.vue +132 -0
  19. package/components/nav/menuPrompt.vue +204 -0
  20. package/components/templates/omsLayout.vue +109 -0
  21. package/config/product/order.js +117 -0
  22. package/config/router/routes.js +39 -2
  23. package/list/IframePage.vue +3 -0
  24. package/list/provisioning.cattle.io.cluster.vue +33 -2
  25. package/package.json +1 -1
  26. package/pages/auth/login.vue +11 -2
  27. package/pages/csm/ServiceMarket-iframe.vue +32 -0
  28. package/pages/csm/order-iframe.vue +32 -0
  29. package/pages/csm/orderInfo-iframe.vue +32 -0
  30. package/pages/csm/shelfist-iframe.vue +32 -0
  31. package/pages/csm/tenant-iframe.vue +32 -0
  32. package/pages/home.vue +1 -1
  33. package/rancher-components/Accordion/Accordion.vue +3 -1
  34. package/rancher-components/RcDropdown/RcDropdown.vue +1 -1
  35. package/scripts/publish-shell.sh +1 -1
  36. package/store/index.js +4 -4
  37. package/store/type-map.js +4 -0
@@ -0,0 +1,132 @@
1
+ <script>
2
+ export default {
3
+ props: {
4
+ position: {
5
+ type: String,
6
+ default: 'bottom-content', // top / bottom / left / right
7
+ validator: v => [
8
+ 'bottom-left', 'bottom-right', 'bottom-content',
9
+ 'top-left', 'top-right', 'top-content'
10
+ ].includes(v)
11
+ }
12
+ }
13
+ };
14
+ </script>
15
+
16
+ <template>
17
+ <div class="menuDropdown" :class="`pos-${position}`">
18
+ <div>
19
+ <slot name="title"></slot>
20
+ </div>
21
+
22
+ <div class="dropdownCollection">
23
+ <slot name="dropdownCollection"></slot>
24
+ </div>
25
+ </div>
26
+ </template>
27
+
28
+ <style lang="scss" scoped>
29
+ .menuDropdown {
30
+ position: relative;
31
+
32
+ .dropdownCollection {
33
+ display: flex;
34
+ flex-direction: column;
35
+
36
+ opacity: 0;
37
+ pointer-events: none;
38
+
39
+ /* === 核心动画:scale + fade + 阴影渐变 === */
40
+ transform: scale(0.95);
41
+ transition:
42
+ opacity 0.22s ease,
43
+ transform 0.22s ease,
44
+ box-shadow 0.22s ease;
45
+
46
+ position: absolute;
47
+ padding: 10px 0;
48
+ border: 1px solid #eee;
49
+ background: #fff;
50
+ z-index: 10;
51
+
52
+ /* 初始阴影弱 */
53
+ box-shadow: 0 0 0 rgba(0, 0, 0, 0.0);
54
+ }
55
+
56
+ &:hover .dropdownCollection {
57
+ opacity: 1;
58
+ pointer-events: auto;
59
+ transform: scale(1);
60
+
61
+ /* 弹出时增加柔和灰色阴影 */
62
+ box-shadow: 0 6px 30px #0000001a;
63
+ }
64
+ }
65
+
66
+ /* ============================
67
+ 方向定位(保持不变)
68
+ ============================ */
69
+ /* ============================
70
+ 新的方向定位(移除 bottom / top)
71
+ ============================ */
72
+
73
+ /* ----- Bottom 系列 ----- */
74
+
75
+ /* bottom-left:在下方,左对齐 */
76
+ .pos-bottom-left .dropdownCollection {
77
+ top: 100%;
78
+ left: 0;
79
+ }
80
+
81
+ /* bottom-right:在下方,右对齐 */
82
+ .pos-bottom-right .dropdownCollection {
83
+ top: 100%;
84
+ right: 0;
85
+ }
86
+
87
+ /* bottom-content:下方,水平居中 */
88
+ .pos-bottom-content .dropdownCollection {
89
+ top: 100%;
90
+ left: 50%;
91
+ transform: translateX(-50%) scale(0.95);
92
+ }
93
+ .menuDropdown.pos-bottom-content:hover .dropdownCollection {
94
+ transform: translateX(-50%) scale(1);
95
+ }
96
+
97
+
98
+ /* ----- Top 系列 ----- */
99
+
100
+ /* top-left:在上方,左对齐 */
101
+ .pos-top-left .dropdownCollection {
102
+ bottom: 100%;
103
+ left: 0;
104
+ }
105
+
106
+ /* top-right:在上方,右对齐 */
107
+ .pos-top-right .dropdownCollection {
108
+ bottom: 100%;
109
+ right: 0;
110
+ }
111
+
112
+ /* top-content:上方,水平居中 */
113
+ .pos-top-content .dropdownCollection {
114
+ bottom: 100%;
115
+ left: 50%;
116
+ transform: translateX(-50%) scale(0.95);
117
+ }
118
+ .menuDropdown.pos-top-content:hover .dropdownCollection {
119
+ transform: translateX(-50%) scale(1);
120
+ }
121
+
122
+
123
+ .pos-left .dropdownCollection {
124
+ top: 0;
125
+ right: 100%;
126
+ }
127
+
128
+ .pos-right .dropdownCollection {
129
+ top: 0;
130
+ left: 100%;
131
+ }
132
+ </style>
@@ -0,0 +1,204 @@
1
+ <script>
2
+ export default {
3
+ props: {
4
+ position: {
5
+ type: String,
6
+ default: 'bottom', // top / bottom / left / right
7
+ validator: v => ['top', 'bottom', 'left', 'right'].includes(v)
8
+ },
9
+ gap: {
10
+ type: Number,
11
+ default: 10 // 弹框距离 title 的 gap
12
+ },
13
+ align: {
14
+ type: String,
15
+ default: 'left',
16
+ validator: v => ['left', 'center', 'right'].includes(v)
17
+ }
18
+ }
19
+ };
20
+ </script>
21
+
22
+ <template>
23
+ <div
24
+ class="menuDropdown"
25
+ :class="[`pos-${position}`, `align-${align}`]"
26
+ :style="{ '--gap': gap + 'px' }"
27
+ >
28
+ <div>
29
+ <slot name="title"></slot>
30
+ </div>
31
+
32
+ <div class="dropdownCollection">
33
+ <slot name="dropdownCollection"></slot>
34
+ </div>
35
+ </div>
36
+ </template>
37
+
38
+ <style lang="scss" scoped>
39
+ .menuDropdown {
40
+ position: relative;
41
+
42
+ .dropdownCollection {
43
+ display: flex;
44
+ flex-direction: column;
45
+ opacity: 0;
46
+ pointer-events: none;
47
+ transform: scale(0.95);
48
+
49
+ transition:
50
+ opacity 0.22s ease,
51
+ transform 0.22s ease,
52
+ box-shadow 0.22s ease;
53
+
54
+ position: absolute;
55
+
56
+ padding: 10px 0;
57
+ border: 1px solid #eee;
58
+ background: #fff;
59
+ z-index: 10;
60
+ box-shadow: 0 0 0 rgba(0, 0, 0, 0);
61
+
62
+ /* 小三角 */
63
+ &::after {
64
+ content: "";
65
+ position: absolute;
66
+ width: 0;
67
+ height: 0;
68
+ border-style: solid;
69
+ opacity: 0;
70
+ transition: opacity 0.22s ease;
71
+ }
72
+ }
73
+
74
+ &:hover .dropdownCollection {
75
+ opacity: 1;
76
+ pointer-events: auto;
77
+ transform: scale(1);
78
+ box-shadow: 0 6px 30px #0000001a;
79
+ }
80
+
81
+ &:hover .dropdownCollection::after {
82
+ opacity: 1;
83
+ }
84
+ }
85
+
86
+ /* ================================
87
+ gap 间距控制
88
+ ================================ */
89
+ .pos-bottom .dropdownCollection {
90
+ top: calc(100% + var(--gap));
91
+ }
92
+
93
+ .pos-top .dropdownCollection {
94
+ bottom: calc(100% + var(--gap));
95
+ }
96
+
97
+ .pos-left .dropdownCollection {
98
+ right: calc(100% + var(--gap));
99
+ }
100
+
101
+ .pos-right .dropdownCollection {
102
+ left: calc(100% + var(--gap));
103
+ }
104
+
105
+ /* ================================
106
+ 三角箭头方向(基础方向)
107
+ ================================ */
108
+
109
+ /* bottom */
110
+ .pos-bottom .dropdownCollection::after {
111
+ bottom: 100%;
112
+ border-width: 0 8px 8px 8px;
113
+ border-color: transparent transparent #fff transparent;
114
+ }
115
+
116
+ /* top */
117
+ .pos-top .dropdownCollection::after {
118
+ top: 100%;
119
+ border-width: 8px 8px 0 8px;
120
+ border-color: #fff transparent transparent transparent;
121
+ }
122
+
123
+ /* left */
124
+ .pos-left .dropdownCollection::after {
125
+ top: 12px;
126
+ left: 100%;
127
+ border-width: 8px 8px 8px 0;
128
+ border-color: transparent #fff transparent transparent;
129
+ }
130
+
131
+ /* right */
132
+ .pos-right .dropdownCollection::after {
133
+ top: 12px;
134
+ right: 100%;
135
+ border-width: 8px 0 8px 8px;
136
+ border-color: transparent transparent transparent #fff;
137
+ }
138
+
139
+ /* ================================
140
+ align 内容对齐方式(影响 dropdown)
141
+ ================================ */
142
+
143
+ /* 内容左对齐 */
144
+ .align-left .dropdownCollection {
145
+ left: 0;
146
+ }
147
+
148
+ /* 内容居中对齐 */
149
+ .align-center .dropdownCollection {
150
+ left: 50%;
151
+ transform: translateX(-50%) scale(0.95);
152
+ }
153
+ .menuDropdown.align-center:hover .dropdownCollection {
154
+ transform: translateX(-50%) scale(1);
155
+ }
156
+
157
+ /* 内容右对齐 */
158
+ .align-right .dropdownCollection {
159
+ right: 0;
160
+ }
161
+
162
+ /* ================================
163
+ 箭头随 align 变化(完整补丁)
164
+ ================================ */
165
+
166
+ /* ===== bottom 系列 ===== */
167
+
168
+ /* left */
169
+ .pos-bottom.align-left .dropdownCollection::after {
170
+ left: 15px;
171
+ }
172
+
173
+ /* center */
174
+ .pos-bottom.align-center .dropdownCollection::after {
175
+ left: 50%;
176
+ transform: translateX(-50%);
177
+ }
178
+
179
+ /* right */
180
+ .pos-bottom.align-right .dropdownCollection::after {
181
+ right: 15px;
182
+ }
183
+
184
+
185
+ /* ===== top 系列 ===== */
186
+
187
+ /* left */
188
+ .pos-top.align-left .dropdownCollection::after {
189
+ left: 15px;
190
+ }
191
+
192
+ /* center */
193
+ .pos-top.align-center .dropdownCollection::after {
194
+ left: 50%;
195
+ transform: translateX(-50%);
196
+ }
197
+
198
+ /* right */
199
+ .pos-top.align-right .dropdownCollection::after {
200
+ right: 15px;
201
+ }
202
+
203
+ /* 左右方向不需要 align,因为箭头垂直居中即可 */
204
+ </style>
@@ -0,0 +1,109 @@
1
+ <script>
2
+ import { mapPref, THEME_SHORTCUT } from '@shell/store/prefs';
3
+ import ActionMenu from '@shell/components/ActionMenu';
4
+ import Header from '@shell/components/nav/Header';
5
+ import PromptRemove from '@shell/components/PromptRemove';
6
+ import IndentedPanel from '@shell/components/IndentedPanel';
7
+ import Brand from '@shell/mixins/brand';
8
+ import FixedBanner from '@shell/components/FixedBanner';
9
+ import GrowlManager from '@shell/components/GrowlManager';
10
+ import ModalManager from '@shell/components/ModalManager';
11
+ import AwsComplianceBanner from '@shell/components/AwsComplianceBanner';
12
+ import AzureWarning from '@shell/components/auth/AzureWarning';
13
+ import BrowserTabVisibility from '@shell/mixins/browser-tab-visibility';
14
+ import { mapGetters } from 'vuex';
15
+ import PromptModal from '@shell/components/PromptModal';
16
+
17
+ export default {
18
+
19
+ components: {
20
+ ActionMenu,
21
+ Header,
22
+ IndentedPanel,
23
+ PromptRemove,
24
+ PromptModal,
25
+ FixedBanner,
26
+ GrowlManager,
27
+ ModalManager,
28
+ AwsComplianceBanner,
29
+ AzureWarning,
30
+ },
31
+
32
+ mixins: [Brand, BrowserTabVisibility],
33
+
34
+ data() {
35
+ return {
36
+ // Assume home pages have routes where the name is the key to use for string lookup
37
+ name: this.$route.name,
38
+ noLocaleShortcut: process.env.dev || false,
39
+ };
40
+ },
41
+
42
+ computed: {
43
+ themeShortcut: mapPref(THEME_SHORTCUT),
44
+ ...mapGetters(['showTopLevelMenu']),
45
+ },
46
+
47
+ methods: {
48
+ toggleTheme() {
49
+ this.$store.dispatch('prefs/toggleTheme');
50
+ },
51
+ toggleNoneLocale() {
52
+ this.$store.dispatch('i18n/toggleNone');
53
+ },
54
+ }
55
+ };
56
+ </script>
57
+
58
+ <template>
59
+ <div class="dashboard-root">
60
+ <div
61
+ class="dashboard-content"
62
+ :class="{'dashboard-padding-left': showTopLevelMenu}"
63
+ >
64
+ <Header :simple="true" />
65
+ <main
66
+ class="main-layout"
67
+ :aria-label="t('layouts.plain')"
68
+ >
69
+ <router-view
70
+ :key="$route.path"
71
+ class="outlet"
72
+ />
73
+ </main>
74
+ </div>
75
+ </div>
76
+ </template>
77
+
78
+ <style lang="scss" scoped>
79
+ .dashboard-root {
80
+ display: flex;
81
+ flex-direction: column;
82
+ height: 100vh;
83
+ }
84
+ .dashboard-content {
85
+ display: grid;
86
+ flex-grow: 1;
87
+
88
+ grid-template-areas:
89
+ "header"
90
+ "main";
91
+
92
+ grid-template-columns: auto;
93
+ grid-template-rows: var(--header-height) auto;
94
+
95
+ > HEADER {
96
+ grid-area: header;
97
+ }
98
+ }
99
+
100
+ MAIN {
101
+ grid-area: main;
102
+ overflow: auto;
103
+
104
+ .outlet {
105
+ min-height: 100%;
106
+ padding: 0;
107
+ }
108
+ }
109
+ </style>
@@ -0,0 +1,117 @@
1
+ import { DSL, IF_HAVE, isAdminUser } from '@shell/store/type-map';
2
+ // import IframePage from '@/shell/list/IframePage.vue';
3
+ export const NAME = 'order';
4
+
5
+
6
+ export function init(store) { // 只传 store
7
+ const { product, virtualType, basicType } = DSL(store, NAME); // DSL 直接用 store 和 NAME
8
+
9
+ let paths = { name: 'c-cluster-order-tenantIframe' }
10
+
11
+ // if (isAdminUser(store.getters)) {
12
+ // paths = { name: 'c-cluster-order-tenantIframe' }
13
+ // } else {
14
+ // paths = { name: 'c-cluster-order-ServiceMarketIframe' }
15
+ // }
16
+
17
+ // 顶级产品
18
+ product({
19
+ ifHave: IF_HAVE.ADMIN,
20
+ inStore: 'management',
21
+ icon: 'extension',
22
+ removable: false,
23
+ showClusterSwitcher: false,
24
+ weight: -10,
25
+ });
26
+
27
+ virtualType({
28
+ ifHave: IF_HAVE.ADMIN,
29
+ label: '租户',
30
+ icon: 'user',
31
+ namespaced: false,
32
+ name: 'tenant-iframe',
33
+ weight: 102,
34
+ route: {
35
+ name: 'c-cluster-order-tenantIframe',
36
+ params: {
37
+ cluster: '_',
38
+ product: NAME,
39
+ }
40
+ }
41
+ });
42
+
43
+ // virtualType({
44
+ // ifHave: IF_HAVE.ADMIN,
45
+ // label: '订单管理',
46
+ // icon: 'user',
47
+ // namespaced: false,
48
+ // name: 'order-iframe',
49
+ // weight: 100,
50
+ // route: {
51
+ // name: 'c-cluster-order-orderIframe',
52
+ // params: {
53
+ // cluster: '_',
54
+ // product: NAME,
55
+ // }
56
+ // }
57
+ // });
58
+
59
+ // // 二级菜单 2:可以增加其他管理页面
60
+ // virtualType({
61
+ // ifHave: IF_HAVE.ADMIN,
62
+ // label: '商品上架',
63
+ // icon: 'user',
64
+ // namespaced: false,
65
+ // name: 'shelfist-iframe',
66
+ // weight: 101,
67
+ // route: {
68
+ // name: 'c-cluster-order-shelfistIframe',
69
+ // params: {
70
+ // cluster: '_',
71
+ // product: NAME,
72
+ // }
73
+ // }
74
+ // });
75
+
76
+ // virtualType({
77
+ // ifHave: IF_HAVE.TENANT,
78
+ // label: '服务市场',
79
+ // icon: 'user',
80
+ // namespaced: false,
81
+ // name: 'ServiceMarket-iframe',
82
+ // weight: 99,
83
+ // route: {
84
+ // name: 'c-cluster-order-ServiceMarketIframe',
85
+ // params: {
86
+ // cluster: '_',
87
+ // product: NAME,
88
+ // }
89
+ // }
90
+ // });
91
+
92
+
93
+ // virtualType({
94
+ // ifHave: IF_HAVE.TENANT,
95
+ // label: '我的订单',
96
+ // icon: 'user',
97
+ // namespaced: false,
98
+ // name: 'orderInfo-iframe',
99
+ // weight: 98,
100
+ // route: {
101
+ // name: 'c-cluster-order-orderInfoIframe',
102
+ // params: {
103
+ // cluster: '_',
104
+ // product: NAME,
105
+ // }
106
+ // }
107
+ // });
108
+
109
+ basicType([
110
+ // 'order-iframe',
111
+ 'tenant-iframe',
112
+ // 'shelfist-iframe',
113
+ // 'ServiceMarket-iframe',
114
+ // 'orderInfo-iframe'
115
+ ]);
116
+
117
+ }
@@ -67,6 +67,19 @@ export default [
67
67
  },
68
68
  ]
69
69
  },
70
+ // {
71
+ // path: '/',
72
+ // component: () => interopDefault(import('@shell/components/templates/omsLayout.vue')),
73
+ // name: 'omsLayout',
74
+ // meta: { requiresAuthentication: true },
75
+ // children: [
76
+ // {
77
+ // path: '/c/:cluster/order/order-iframe',
78
+ // component: () => interopDefault(import('@shell/pages/csm/order-iframe.vue')),
79
+ // name: 'c-cluster-order-iframe'
80
+ // },
81
+ // ]
82
+ // },
70
83
  {
71
84
  path: '/',
72
85
  component: () => interopDefault(import('@shell/components/templates/plain.vue')),
@@ -169,6 +182,31 @@ export default [
169
182
  name: 'default',
170
183
  meta: { requiresAuthentication: true },
171
184
  children: [
185
+ {
186
+ path: '/c/:cluster/order/orderInfo-iframe',
187
+ component: () => interopDefault(import('@shell/pages/csm/orderInfo-iframe.vue')),
188
+ name: 'c-cluster-order-orderInfoIframe'
189
+ },
190
+ {
191
+ path: '/c/:cluster/order/ServiceMarket-iframe',
192
+ component: () => interopDefault(import('@shell/pages/csm/ServiceMarket-iframe.vue')),
193
+ name: 'c-cluster-order-ServiceMarketIframe'
194
+ },
195
+ {
196
+ path: '/c/:cluster/order/shelfist-iframe',
197
+ component: () => interopDefault(import('@shell/pages/csm/shelfist-iframe.vue')),
198
+ name: 'c-cluster-order-shelfistIframe'
199
+ },
200
+ {
201
+ path: '/c/:cluster/order/order-iframe',
202
+ component: () => interopDefault(import('@shell/pages/csm/order-iframe.vue')),
203
+ name: 'c-cluster-order-orderIframe'
204
+ },
205
+ {
206
+ path: '/c/:cluster/order/tenant-iframe',
207
+ component: () => interopDefault(import('@shell/pages/csm/tenant-iframe.vue')),
208
+ name: 'c-cluster-order-tenantIframe'
209
+ },
172
210
  {
173
211
  path: '/clusters',
174
212
  component: () => interopDefault(import('@shell/pages/clusters/index.vue')),
@@ -330,8 +368,7 @@ export default [
330
368
  },
331
369
  },
332
370
  ]
333
- },
334
- {
371
+ }, {
335
372
  path: '/c/:cluster/auth/config',
336
373
  component: () => interopDefault(import('@shell/pages/c/_cluster/auth/config/index.vue')),
337
374
  name: 'c-cluster-auth-config'
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <div>2222222</div>
3
+ </template>
@@ -303,7 +303,38 @@ export default {
303
303
  </div>
304
304
  </td>
305
305
  </template>
306
- <template #cell:explorer="{row}">
306
+ <!-- ==============================
307
+ name 列 → 使用 explorer 的行为
308
+ ============================== -->
309
+ <template #cell:name="{ row }">
310
+ <router-link
311
+ v-if="row.mgmt && row.mgmt.isReady && !row.hasError"
312
+ data-testid="cluster-manager-list-explore-management"
313
+ :to="{name: 'c-cluster', params: {cluster: row.mgmt.id}}"
314
+ >
315
+ <a href="javascript:;">
316
+ {{ row.nameDisplay || row.name }}
317
+ </a>
318
+ </router-link>
319
+
320
+ <span v-else>
321
+ {{ row.nameDisplay || row.name }}
322
+ </span>
323
+ </template>
324
+
325
+ <!-- ==========================================
326
+ explorer 列 → 使用 name 原本的导航行为
327
+ ========================================== -->
328
+ <template #cell:explorer="{ row }">
329
+ <router-link
330
+ :to="row._detailLocation || row.listLocation"
331
+ >
332
+ <a href="javascript:;">
333
+ {{ t('cluster.explore') }}
334
+ </a>
335
+ </router-link>
336
+ </template>
337
+ <!-- <template #cell:explorer="{row}">
307
338
  <router-link
308
339
  v-if="row.mgmt && row.mgmt.isReady && !row.hasError"
309
340
  data-testid="cluster-manager-list-explore-management"
@@ -319,7 +350,7 @@ export default {
319
350
  >
320
351
  {{ t('cluster.explore') }}
321
352
  </span>
322
- </template>
353
+ </template> -->
323
354
  </ResourceTable>
324
355
  </div>
325
356
  </template>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashboard-shell-shell",
3
- "version": "3.0.5-logtest.2",
3
+ "version": "3.0.5-order.1",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",