@opendesign-plus/components 0.0.1-rc.10

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 (199) hide show
  1. package/dist/chunk-OElCookieNotice.cjs.js +1 -0
  2. package/dist/chunk-OElCookieNotice.es.js +833 -0
  3. package/dist/components/OBanner.vue.d.ts +11 -0
  4. package/dist/components/OCookieNotice.vue.d.ts +17 -0
  5. package/dist/components/OFooter.vue.d.ts +46 -0
  6. package/dist/components/OHeaderSearch.vue.d.ts +692 -0
  7. package/dist/components/OHeaderUser.vue.d.ts +38 -0
  8. package/dist/components/OPlusConfigProvider.vue.d.ts +23 -0
  9. package/dist/components/OSection.vue.d.ts +37 -0
  10. package/dist/components/OSourceCode.vue.d.ts +20 -0
  11. package/dist/components/OThemeSwitcher.vue.d.ts +28 -0
  12. package/dist/components/activity/OActivityApproval.vue.d.ts +277 -0
  13. package/dist/components/activity/OActivityForm.vue.d.ts +140 -0
  14. package/dist/components/activity/OMyActivityCalendar.vue.d.ts +578 -0
  15. package/dist/components/activity/config.d.ts +15 -0
  16. package/dist/components/activity/index.d.ts +623 -0
  17. package/dist/components/activity/types.d.ts +81 -0
  18. package/dist/components/element-plus/OElCookieNotice.vue.d.ts +34 -0
  19. package/dist/components/element-plus/index.d.ts +2 -0
  20. package/dist/components/events/OEventsApply.vue.d.ts +16 -0
  21. package/dist/components/events/OEventsCalendar.vue.d.ts +5 -0
  22. package/dist/components/events/OEventsList.vue.d.ts +26 -0
  23. package/dist/components/events/config.d.ts +27 -0
  24. package/dist/components/events/index.d.ts +78 -0
  25. package/dist/components/events/types.d.ts +66 -0
  26. package/dist/components/events/utils.d.ts +7 -0
  27. package/dist/components/header/OHeader.vue.d.ts +24 -0
  28. package/dist/components/header/OHeaderMoblie.vue.d.ts +33 -0
  29. package/dist/components/header/components/HeaderContent.vue.d.ts +6 -0
  30. package/dist/components/header/components/HeaderNav.vue.d.ts +7 -0
  31. package/dist/components/header/components/HeaderNavMoblie.vue.d.ts +17 -0
  32. package/dist/components/header/components/HeaderUbmcNav.vue.d.ts +2 -0
  33. package/dist/components/header/index.d.ts +22 -0
  34. package/dist/components/meeting/OMeetingCalendar.vue.d.ts +298 -0
  35. package/dist/components/meeting/OMeetingForm.vue.d.ts +145 -0
  36. package/dist/components/meeting/OMyMeetingCalendar.vue.d.ts +586 -0
  37. package/dist/components/meeting/OSigMeetingCalendar.vue.d.ts +24 -0
  38. package/dist/components/meeting/components/OMeetingCalendarList.vue.d.ts +28 -0
  39. package/dist/components/meeting/components/OMeetingCalendarSelector.vue.d.ts +664 -0
  40. package/dist/components/meeting/components/OMeetingDetail.vue.d.ts +12 -0
  41. package/dist/components/meeting/components/OMeetingPlaybackSubtitles.vue.d.ts +5 -0
  42. package/dist/components/meeting/components/OMeetingPlaybackVideo.vue.d.ts +17 -0
  43. package/dist/components/meeting/components/OSigMeetingAside.vue.d.ts +16 -0
  44. package/dist/components/meeting/config.d.ts +27 -0
  45. package/dist/components/meeting/types.d.ts +166 -0
  46. package/dist/components/meeting/utils.d.ts +22 -0
  47. package/dist/components.cjs.js +224 -0
  48. package/dist/components.css +1 -0
  49. package/dist/components.element.cjs.js +1 -0
  50. package/dist/components.element.es.js +4 -0
  51. package/dist/components.es.js +45054 -0
  52. package/dist/index.d.ts +19 -0
  53. package/docs/design.md +27 -0
  54. package/docs/design_banner.md +41 -0
  55. package/docs/design_section.md +27 -0
  56. package/package.json +56 -0
  57. package/scripts/generate-components-index.js +104 -0
  58. package/src/assets/events/svg-icons/icon-checked.svg +3 -0
  59. package/src/assets/events/svg-icons/icon-competition.svg +7 -0
  60. package/src/assets/events/svg-icons/icon-events.svg +4 -0
  61. package/src/assets/events/svg-icons/icon-release.svg +4 -0
  62. package/src/assets/events/svg-icons/icon-summit.svg +4 -0
  63. package/src/assets/meeting/svg-icons/icon-all.svg +3 -0
  64. package/src/assets/meeting/svg-icons/icon-backward.svg +4 -0
  65. package/src/assets/meeting/svg-icons/icon-calendar.svg +3 -0
  66. package/src/assets/meeting/svg-icons/icon-cancel.svg +4 -0
  67. package/src/assets/meeting/svg-icons/icon-captions.svg +4 -0
  68. package/src/assets/meeting/svg-icons/icon-close-captions.svg +6 -0
  69. package/src/assets/meeting/svg-icons/icon-close-fullscreen.svg +6 -0
  70. package/src/assets/meeting/svg-icons/icon-copy.svg +3 -0
  71. package/src/assets/meeting/svg-icons/icon-create.svg +5 -0
  72. package/src/assets/meeting/svg-icons/icon-delete.svg +7 -0
  73. package/src/assets/meeting/svg-icons/icon-empty.svg +31 -0
  74. package/src/assets/meeting/svg-icons/icon-empty_dark.svg +49 -0
  75. package/src/assets/meeting/svg-icons/icon-event.svg +3 -0
  76. package/src/assets/meeting/svg-icons/icon-export.svg +3 -0
  77. package/src/assets/meeting/svg-icons/icon-forward.svg +4 -0
  78. package/src/assets/meeting/svg-icons/icon-fullscreen.svg +6 -0
  79. package/src/assets/meeting/svg-icons/icon-help.svg +3 -0
  80. package/src/assets/meeting/svg-icons/icon-important.svg +4 -0
  81. package/src/assets/meeting/svg-icons/icon-info.svg +3 -0
  82. package/src/assets/meeting/svg-icons/icon-meet.svg +3 -0
  83. package/src/assets/meeting/svg-icons/icon-meeting-message.svg +5 -0
  84. package/src/assets/meeting/svg-icons/icon-meeting.svg +4 -0
  85. package/src/assets/meeting/svg-icons/icon-play.svg +5 -0
  86. package/src/assets/meeting/svg-icons/icon-playing-tip.svg +7 -0
  87. package/src/assets/meeting/svg-icons/icon-playing.svg +5 -0
  88. package/src/assets/meeting/svg-icons/icon-question.svg +4 -0
  89. package/src/assets/meeting/svg-icons/icon-sound.svg +5 -0
  90. package/src/assets/meeting/svg-icons/icon-speaker.svg +3 -0
  91. package/src/assets/meeting/svg-icons/icon-summit.svg +3 -0
  92. package/src/assets/meeting/svg-icons/icon-telligent.svg +3 -0
  93. package/src/assets/meeting/svg-icons/icon-tip.svg +3 -0
  94. package/src/assets/meeting/svg-icons/icon-todo.svg +4 -0
  95. package/src/assets/meeting/transparent.png +0 -0
  96. package/src/assets/svg-icons/icon-arrow-left.svg +3 -0
  97. package/src/assets/svg-icons/icon-avatar-line.svg +3 -0
  98. package/src/assets/svg-icons/icon-caret-left.svg +3 -0
  99. package/src/assets/svg-icons/icon-caret-right.svg +3 -0
  100. package/src/assets/svg-icons/icon-chevron-down.svg +3 -0
  101. package/src/assets/svg-icons/icon-chevron-right.svg +3 -0
  102. package/src/assets/svg-icons/icon-chevron-up.svg +3 -0
  103. package/src/assets/svg-icons/icon-close.svg +3 -0
  104. package/src/assets/svg-icons/icon-delete.svg +3 -0
  105. package/src/assets/svg-icons/icon-filter.svg +3 -0
  106. package/src/assets/svg-icons/icon-header-back.svg +3 -0
  107. package/src/assets/svg-icons/icon-header-delete.svg +3 -0
  108. package/src/assets/svg-icons/icon-header-menu.svg +3 -0
  109. package/src/assets/svg-icons/icon-header-person.svg +3 -0
  110. package/src/assets/svg-icons/icon-header-search.svg +4 -0
  111. package/src/assets/svg-icons/icon-loading.svg +4 -0
  112. package/src/assets/svg-icons/icon-locale.svg +3 -0
  113. package/src/assets/svg-icons/icon-log-off.svg +3 -0
  114. package/src/assets/svg-icons/icon-message.svg +3 -0
  115. package/src/assets/svg-icons/icon-moon.svg +3 -0
  116. package/src/assets/svg-icons/icon-outlink.svg +3 -0
  117. package/src/assets/svg-icons/icon-overview.svg +3 -0
  118. package/src/assets/svg-icons/icon-search.svg +3 -0
  119. package/src/assets/svg-icons/icon-setting.svg +3 -0
  120. package/src/assets/svg-icons/icon-sun.svg +3 -0
  121. package/src/assets/svg-icons/icon-tips.svg +3 -0
  122. package/src/components/OBanner.vue +398 -0
  123. package/src/components/OCookieNotice.vue +575 -0
  124. package/src/components/OFooter.vue +576 -0
  125. package/src/components/OHeaderSearch.vue +601 -0
  126. package/src/components/OHeaderUser.vue +237 -0
  127. package/src/components/OPlusConfigProvider.vue +32 -0
  128. package/src/components/OSection.vue +178 -0
  129. package/src/components/OSourceCode.vue +153 -0
  130. package/src/components/OThemeSwitcher.vue +108 -0
  131. package/src/components/activity/OActivityApproval.vue +871 -0
  132. package/src/components/activity/OActivityForm.vue +548 -0
  133. package/src/components/activity/OMyActivityCalendar.vue +1501 -0
  134. package/src/components/activity/config.ts +141 -0
  135. package/src/components/activity/index.ts +24 -0
  136. package/src/components/activity/types.ts +88 -0
  137. package/src/components/common/AppAvatar.vue +83 -0
  138. package/src/components/common/ClientOnlyWrapper.ts +21 -0
  139. package/src/components/common/ContentWrapper.vue +85 -0
  140. package/src/components/common/MoreText.vue +124 -0
  141. package/src/components/common/ThFilter.vue +330 -0
  142. package/src/components/element-plus/OElCookieNotice.vue +603 -0
  143. package/src/components/element-plus/index.ts +3 -0
  144. package/src/components/events/OEventsApply.vue +419 -0
  145. package/src/components/events/OEventsCalendar.vue +588 -0
  146. package/src/components/events/OEventsList.vue +354 -0
  147. package/src/components/events/config.ts +35 -0
  148. package/src/components/events/index.ts +24 -0
  149. package/src/components/events/types.ts +80 -0
  150. package/src/components/events/utils.ts +9 -0
  151. package/src/components/header/OHeader.vue +175 -0
  152. package/src/components/header/OHeaderMoblie.vue +152 -0
  153. package/src/components/header/components/HeaderContent.vue +942 -0
  154. package/src/components/header/components/HeaderNav.vue +280 -0
  155. package/src/components/header/components/HeaderNavMoblie.vue +346 -0
  156. package/src/components/header/components/HeaderUbmcNav.vue +540 -0
  157. package/src/components/header/index.ts +16 -0
  158. package/src/components/meeting/OMeetingCalendar.vue +900 -0
  159. package/src/components/meeting/OMeetingForm.vue +1041 -0
  160. package/src/components/meeting/OMeetingPlayback.vue +439 -0
  161. package/src/components/meeting/OMyMeetingCalendar.vue +1502 -0
  162. package/src/components/meeting/OSigMeetingCalendar.vue +411 -0
  163. package/src/components/meeting/components/OMeetingCalendarList.vue +505 -0
  164. package/src/components/meeting/components/OMeetingCalendarSelector.vue +206 -0
  165. package/src/components/meeting/components/OMeetingDetail.vue +227 -0
  166. package/src/components/meeting/components/OMeetingPlaybackSubtitles.vue +611 -0
  167. package/src/components/meeting/components/OMeetingPlaybackVideo.vue +741 -0
  168. package/src/components/meeting/components/OSigMeetingAside.vue +197 -0
  169. package/src/components/meeting/config.ts +121 -0
  170. package/src/components/meeting/index.ts +45 -0
  171. package/src/components/meeting/types.ts +193 -0
  172. package/src/components/meeting/utils.ts +123 -0
  173. package/src/draft/Banner.vue +265 -0
  174. package/src/draft/ButtonCards.vue +106 -0
  175. package/src/draft/Feature.vue +134 -0
  176. package/src/draft/Footer.vue +512 -0
  177. package/src/draft/HorizontalAnchor.vue +165 -0
  178. package/src/draft/ItemSwiper.vue +133 -0
  179. package/src/draft/Logo.vue +141 -0
  180. package/src/draft/LogoCard.vue +75 -0
  181. package/src/draft/LogoV2.vue +19 -0
  182. package/src/draft/MainCard.vue +38 -0
  183. package/src/draft/MultiCard.vue +95 -0
  184. package/src/draft/MultiIconCard.vue +74 -0
  185. package/src/draft/OInfoCard.vue +176 -0
  186. package/src/draft/Process.vue +81 -0
  187. package/src/draft/Section.vue +167 -0
  188. package/src/draft/SingleTabCard.vue +85 -0
  189. package/src/draft/SliderCard.vue +110 -0
  190. package/src/env.d.ts +16 -0
  191. package/src/i18n/en.ts +261 -0
  192. package/src/i18n/index.ts +56 -0
  193. package/src/i18n/zh.ts +250 -0
  194. package/src/index.ts +45 -0
  195. package/src/shared/provide.ts +6 -0
  196. package/src/shims-vue-dompurify-html.d.ts +17 -0
  197. package/src/vue.d.ts +10 -0
  198. package/tsconfig.json +37 -0
  199. package/vite.config.ts +118 -0
@@ -0,0 +1,280 @@
1
+ <script setup lang="ts">
2
+ import { ref, onMounted, onUnmounted, nextTick } from 'vue';
3
+ import { OIcon, OTag } from '@opensig/opendesign';
4
+
5
+ import IconCaretLeft from '~icons/components/icon-caret-left.svg';
6
+ import IconCaretRight from '~icons/components/icon-caret-right.svg';
7
+
8
+ import { useTheme } from '@opendesign-plus/composables';
9
+
10
+ import { useDebounceFn } from '@vueuse/core';
11
+
12
+ export interface OHeaderEmitsT {
13
+ (e: 'handle-mouseenter', val: any): void;
14
+ (e: 'handle-mouseleave', val: any): void;
15
+ (e: 'handle-click', val: any): void;
16
+ }
17
+
18
+ const emit = defineEmits<OHeaderEmitsT>();
19
+ const { isDark } = useTheme();
20
+
21
+ const props = defineProps({
22
+ navData: undefined,
23
+ activeIndex: undefined,
24
+ hoverId: undefined,
25
+ });
26
+
27
+ const navRef = ref();
28
+ const navListRef = ref();
29
+ const resizeTimer = ref(null);
30
+ const navVisibleRight = ref(false);
31
+ const navVisibleLeft = ref(false);
32
+
33
+ const hoverIndex = ref();
34
+
35
+ const toggleDebounced = useDebounceFn((item: any | null, id: string) => {
36
+ hoverIndex.value = item?.id;
37
+ if (id === 'mouseenter') {
38
+ emit('handle-mouseenter', item);
39
+ }
40
+ if (id === 'mouseleave') {
41
+ hoverIndex.value = '';
42
+ emit('handle-mouseleave', item);
43
+ }
44
+ }, 100);
45
+
46
+ const handleClick = (item: any) => {
47
+ emit('handle-click', item);
48
+ };
49
+
50
+ const scrollNavRight = () => {
51
+ navVisibleLeft.value = true;
52
+ nextTick(() => {
53
+ navRef.value.scrollTo({
54
+ left: navRef.value.clientWidth,
55
+ behavior: 'smooth',
56
+ });
57
+ });
58
+ };
59
+ const scrollNavLeft = () => {
60
+ navRef.value.scrollTo({
61
+ left: 0,
62
+ behavior: 'smooth',
63
+ });
64
+ navVisibleLeft.value = false;
65
+ };
66
+
67
+ const calculateLayout = () => {
68
+ if (navRef.value?.clientWidth < navListRef.value?.clientWidth) {
69
+ navVisibleRight.value = true;
70
+ } else {
71
+ navVisibleRight.value = false;
72
+ }
73
+ };
74
+
75
+ // ------------导航埋点------------
76
+ // 首次hover时间
77
+ let hoverTime = 0;
78
+ // 最终点击导航所用步骤
79
+ let steps = 0;
80
+
81
+ const onHoverHeader = () => (steps = 0);
82
+
83
+ const onHoverNav = (name: string) => {
84
+ if (steps > 0) return void steps++;
85
+ steps++;
86
+ hoverTime = Date.now();
87
+ return {
88
+ event: 'hover',
89
+ properties: {
90
+ module: 'navigation',
91
+ level1: name,
92
+ target: name,
93
+ },
94
+ };
95
+ };
96
+
97
+ const onClickNavItem = (item: any) => {
98
+ const res = {
99
+ properties: {
100
+ module: 'navigation',
101
+ level1: item.label,
102
+ target: item.label,
103
+ steps: steps,
104
+ url: item.href,
105
+ duration: Date.now() - hoverTime,
106
+ },
107
+ };
108
+ return res;
109
+ };
110
+
111
+ onMounted(() => {
112
+ window.addEventListener('resize', calculateLayout);
113
+ // 确保 DOM 完全渲染后再计算
114
+ nextTick(() => {
115
+ calculateLayout();
116
+ resizeTimer.value = setTimeout(() => {
117
+ calculateLayout();
118
+ }, 1000);
119
+ });
120
+ });
121
+
122
+ // 清理
123
+ onUnmounted(() => {
124
+ window.removeEventListener('resize', calculateLayout);
125
+ clearTimeout(resizeTimer.value);
126
+ });
127
+ </script>
128
+
129
+ <template>
130
+ <div class="header-nav-wrap">
131
+ <div class="header-nav" :class="{ 'header-nav-scroll': navVisibleLeft }">
132
+ <div class="right-icon" v-if="navVisibleLeft">
133
+ <OIcon @click="scrollNavLeft"><IconCaretLeft /></OIcon>
134
+ </div>
135
+ <div ref="navRef" class="o-nav" :class="{ 'o-nav-scroll': navVisibleLeft || !navVisibleRight, dark: isDark }">
136
+ <ul ref="navListRef" class="o-nav-list" @mouseenter="onHoverHeader">
137
+ <li
138
+ v-for="(item, idx) in navData"
139
+ :key="item.id"
140
+ :class="{
141
+ 'is-selected': hoverIndex === item.id || props.hoverId === item.id,
142
+ 'is-active': props.activeIndex === idx,
143
+ }"
144
+ @mouseenter="toggleDebounced(item, 'mouseenter')"
145
+ @mouseleave="toggleDebounced(item, 'mouseleave')"
146
+ v-analytics:mouseenter="onHoverNav(item.label)"
147
+ v-analytics.catchBubble="onClickNavItem(item)"
148
+ >
149
+ <div v-if="item?.children?.length" :id="'tour_headerNav_' + item.id" class="nav-item">
150
+ <span class="nav-text">{{ item.label }}</span>
151
+ </div>
152
+ <div v-else :id="'tour_headerNav_' + item.id" class="nav-item item-other" @click="handleClick(item)">
153
+ <span class="nav-text">{{ item.label }}</span>
154
+ <OTag v-if="item.tag" round="pill" color="danger" size="small" class="content-tag">{{ item.tag }}</OTag>
155
+ </div>
156
+ </li>
157
+ </ul>
158
+ </div>
159
+ <div class="right-icon" v-if="navVisibleRight && !navVisibleLeft">
160
+ <OIcon @click="scrollNavRight"><IconCaretRight /></OIcon>
161
+ </div>
162
+ </div>
163
+ </div>
164
+ </template>
165
+
166
+ <style lang="scss" scoped>
167
+ .header-nav-wrap {
168
+ height: 100%;
169
+ .header-nav {
170
+ height: 100%;
171
+ display: flex;
172
+ justify-content: space-between;
173
+ width: calc(100% - 64px);
174
+ align-items: center;
175
+ }
176
+ .header-nav-scroll {
177
+ width: calc(100% - 64px - 24px);
178
+ }
179
+ }
180
+ .o-nav {
181
+ height: 100%;
182
+ position: relative;
183
+ overflow-y: hidden;
184
+ overflow-x: auto;
185
+ &::after {
186
+ content: '';
187
+ position: absolute;
188
+ width: 50px;
189
+ height: 100%;
190
+ right: 0;
191
+ top: 0;
192
+ background-image: linear-gradient(90deg, rgba(var(--o-mixedgray-1), 0) 0%, rgba(var(--o-mixedgray-1), 1) 100%);
193
+ z-index: 0;
194
+ }
195
+ &::-webkit-scrollbar {
196
+ display: none;
197
+ }
198
+ &.dark {
199
+ &::after {
200
+ background-image: linear-gradient(90deg, rgba(var(--o-mixedgray-4), 0) 0%, rgba(var(--o-mixedgray-4), 1) 100%);
201
+ }
202
+ }
203
+ }
204
+ .o-nav-scroll {
205
+ &::after {
206
+ display: none;
207
+ }
208
+ }
209
+ .o-nav-list {
210
+ display: flex;
211
+ height: 100%;
212
+ width: fit-content;
213
+ flex-wrap: nowrap;
214
+ white-space: nowrap;
215
+ padding: 0;
216
+ margin: 0;
217
+ li {
218
+ position: relative;
219
+ display: flex;
220
+ align-items: center;
221
+ height: 100%;
222
+ color: var(--o-color-info1);
223
+ transition: all var(--o-duration-s) var(--o-easing-standard);
224
+ .nav-text {
225
+ position: relative;
226
+ &::after {
227
+ content: '';
228
+ position: absolute;
229
+ left: 0;
230
+ opacity: 0;
231
+ bottom: -24px;
232
+ width: 100%;
233
+ height: 2px;
234
+ border-radius: 1px;
235
+ background: var(--o-color-primary1);
236
+ transition: all var(--o-duration-s) var(--o-easing-standard);
237
+ }
238
+ }
239
+ &.is-selected,
240
+ &.is-active {
241
+ .nav-text {
242
+ color: var(--o-color-primary1);
243
+ z-index: 99;
244
+ font-weight: 500;
245
+ &::after {
246
+ content: '';
247
+ opacity: 1;
248
+ }
249
+ }
250
+ }
251
+ }
252
+
253
+ .nav-item {
254
+ cursor: default;
255
+ display: flex;
256
+ align-items: center;
257
+ padding: 22px var(--o-gap-4);
258
+ @include text1;
259
+
260
+ @include respond-to('laptop') {
261
+ padding: 22px 12px;
262
+ }
263
+ @include respond-to('pad_h') {
264
+ padding: 22px 8px;
265
+ }
266
+ &.en {
267
+ @media (min-width: 841px) and (max-width: 1000px) {
268
+ padding: var(--o-gap-2);
269
+ }
270
+ }
271
+ }
272
+ .item-other {
273
+ cursor: pointer;
274
+ .content-tag {
275
+ margin-left: var(--o-gap-2);
276
+ --layout-pkg-radius: var(--o-radius-xs);
277
+ }
278
+ }
279
+ }
280
+ </style>
@@ -0,0 +1,346 @@
1
+ <script lang="ts" setup>
2
+ import { ref, onMounted, watch } from 'vue';
3
+ import { OIcon, OTag } from '@opensig/opendesign';
4
+
5
+ const props = defineProps({
6
+ menuShow: {
7
+ type: Boolean,
8
+ default() {
9
+ return false;
10
+ },
11
+ },
12
+ navData: undefined,
13
+ codeData: undefined,
14
+ });
15
+
16
+ const navActive = ref('');
17
+ const navInfo = ref({});
18
+
19
+ const handleNavClick = (item: any) => {
20
+ if (item?.href) {
21
+ window.open(item?.href, '_self');
22
+ return true;
23
+ }
24
+ if (!item) {
25
+ navActive.value = 'source_code';
26
+ navInfo.value = props.codeData.list;
27
+ } else {
28
+ navActive.value = item.id;
29
+ navInfo.value = item;
30
+ }
31
+ };
32
+
33
+ const emit = defineEmits(['link-click']);
34
+ const linkClick = (url: string, target?: string) => {
35
+ window.open(url, target ? target : '_self');
36
+ emit('link-click');
37
+ };
38
+
39
+ onMounted(() => {
40
+ navActive.value = props.navData[0].id;
41
+ navInfo.value = props.navData[0];
42
+ });
43
+
44
+ watch(
45
+ () => props.navData || props.codeData,
46
+ () => {
47
+ navInfo.value = navActive.value === 'source_code' ? props.codeData.list : props.navData.find((item) => item.id === navActive.value);
48
+ },
49
+ {
50
+ deep: true,
51
+ }
52
+ );
53
+ </script>
54
+
55
+ <template>
56
+ <div class="header-content-mb">
57
+ <div class="header-nav" :class="{ active: menuShow }">
58
+ <div class="o-nav">
59
+ <ul class="o-nav-list">
60
+ <li
61
+ v-for="item in navData"
62
+ :key="item.id"
63
+ :class="{
64
+ active: navActive === item.id,
65
+ }"
66
+ >
67
+ <span @click="handleNavClick(item)">{{ item.label }}</span>
68
+ </li>
69
+ </ul>
70
+ <div class="nav-aside">
71
+ <ul v-if="navActive !== 'source_code'" class="nav-aside-wrapper">
72
+ <li v-for="item in navInfo.children" :value="item.label" :title="item.label" :key="item.label" class="nav-aside-content">
73
+ <template v-if="item?.children">
74
+ <p class="content-label">{{ item.label }}</p>
75
+ <div class="container-mobile">
76
+ <div v-for="subItem in item?.children" :key="subItem.label" class="content-container-mobile">
77
+ <a @click="linkClick(subItem.href, subItem?.target)" rel="noopener noreferrer" class="content-subtitle">
78
+ <span class="item-label">{{ subItem.label }}</span>
79
+ <OIcon v-if="subItem.icon">
80
+ <component :is="subItem.icon" class="icon" />
81
+ </OIcon>
82
+ <OTag v-if="subItem.tag" round="pill" color="danger" size="small" class="content-tag">{{ subItem.tag }}</OTag>
83
+ </a>
84
+ <div class="desc-container">
85
+ <p class="item-desc">{{ subItem.description }}</p>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ </template>
90
+ <template v-else>
91
+ <a @click="linkClick(item.href, item?.target)" rel="noopener noreferrer" class="content-subtitle item-not-children">
92
+ <span class="item-label">{{ item.label }}</span>
93
+ <OIcon v-if="item.icon">
94
+ <component :is="item.icon" class="icon" />
95
+ </OIcon>
96
+ <OTag v-if="item.tag" round="pill" color="danger" size="small">{{ item.tag }}</OTag>
97
+ </a>
98
+ </template>
99
+ </li>
100
+ </ul>
101
+ <div v-else class="nav-aside-wrapper">
102
+ <a v-for="item in navInfo" :key="item.label" @click="linkClick(item.href, item?.target)" class="source-code-item">
103
+ <span>{{ item.label }}</span>
104
+ <OIcon v-if="item.icon">
105
+ <component :is="item.icon" class="icon" />
106
+ </OIcon>
107
+ </a>
108
+ </div>
109
+ </div>
110
+ </div>
111
+ <!-- 移动端 tool -->
112
+ <div class="header-tool">
113
+ <!-- 源码 -->
114
+ <div
115
+ v-if="codeData"
116
+ class="header-tool-code"
117
+ @click="handleNavClick(null)"
118
+ :class="{
119
+ active: navActive === 'source_code',
120
+ }"
121
+ >
122
+ {{ codeData.label }}
123
+ </div>
124
+ <div v-if="$slots.tool">
125
+ <slot name="tool"></slot>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </template>
131
+
132
+ <style lang="scss" scoped>
133
+ @mixin nav-item {
134
+ display: flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ height: 48px;
138
+ color: var(--o-color-info1);
139
+
140
+ &.active {
141
+ color: var(--o-color-primary1);
142
+ background: var(--o-color-fill2);
143
+ font-weight: 500;
144
+ }
145
+ }
146
+
147
+ .header-content-mb {
148
+ position: fixed;
149
+ top: var(--o-header-height);
150
+ bottom: 0;
151
+ left: 0;
152
+ right: 0;
153
+ background-color: var(--o-color-fill2);
154
+ z-index: 98;
155
+ }
156
+
157
+ .header-nav {
158
+ flex: 1;
159
+ justify-content: space-between;
160
+ width: 100%;
161
+ position: fixed;
162
+ left: 0;
163
+ overflow: hidden;
164
+ top: var(--o-header-height);
165
+ height: calc(100vh - var(--o-header-height));
166
+ transform: translateX(-130%);
167
+
168
+ transition-duration: 0.333s;
169
+ transition-property: all;
170
+ transition-timing-function: cubic-bezier(0.5, 0, 0.84, 0.25);
171
+ display: block;
172
+ opacity: 0;
173
+
174
+ &.active {
175
+ opacity: 1;
176
+ visibility: visible;
177
+ transform: translateX(0);
178
+ }
179
+ }
180
+
181
+ .o-nav {
182
+ height: 100%;
183
+ position: relative;
184
+ width: 99px;
185
+ background: var(--o-color-fill1);
186
+ display: flex;
187
+ flex-direction: column;
188
+ justify-content: space-between;
189
+
190
+ .o-nav-list {
191
+ padding: 0;
192
+ margin: 0;
193
+ height: auto;
194
+
195
+ > li {
196
+ position: relative;
197
+ text-align: center;
198
+ @include text2;
199
+ @include nav-item;
200
+ }
201
+ }
202
+ }
203
+
204
+ .nav-aside {
205
+ position: fixed;
206
+ background-color: var(--o-color-fill2);
207
+ top: 0;
208
+ left: 0;
209
+ width: calc(100% - 99px);
210
+ transform: translateX(99px);
211
+ height: 100%;
212
+ z-index: 190;
213
+ .nav-aside-wrapper {
214
+ overflow-y: auto;
215
+ padding: 16px 12px 32px;
216
+ height: 100%;
217
+ .nav-aside-content {
218
+ display: block;
219
+ flex: 0 1 auto;
220
+
221
+ & + .nav-aside-content {
222
+ position: relative;
223
+ padding-top: var(--o-gap-3);
224
+ &::before {
225
+ content: '';
226
+ position: absolute;
227
+ top: 0;
228
+ width: 100%;
229
+ height: 1px;
230
+ background-color: rgba(var(--o-mixedgray-14), 0.1);
231
+ }
232
+ }
233
+ .content-label {
234
+ color: var(--o-color-info3);
235
+ @include text2;
236
+ }
237
+
238
+ .item-not-children {
239
+ margin-bottom: 12px;
240
+ display: flex;
241
+ align-items: center;
242
+ .o-tag {
243
+ margin-left: var(--o-gap-2);
244
+ --layout-pkg-radius: 100vh;
245
+ }
246
+ .o-icon {
247
+ margin-left: var(--o-gap-2);
248
+ }
249
+ }
250
+ }
251
+
252
+ .source-code-item {
253
+ height: 40px;
254
+ display: flex;
255
+ align-items: center;
256
+ color: var(--o-color-primary1);
257
+
258
+ & + .source-code-item {
259
+ border-top: 1px solid var(--o-color-control4);
260
+ }
261
+
262
+ .icon {
263
+ margin-left: var(--o-gap-2);
264
+ }
265
+ }
266
+
267
+ &::-webkit-scrollbar-track {
268
+ border-radius: 3px;
269
+ }
270
+
271
+ &::-webkit-scrollbar {
272
+ width: 6px;
273
+ background-color: transparent;
274
+ }
275
+
276
+ &::-webkit-scrollbar-thumb {
277
+ border-radius: 3px;
278
+ background: var(--o-color-control1);
279
+ }
280
+ }
281
+
282
+ .container-mobile {
283
+ margin-top: 8px;
284
+ @include text2;
285
+
286
+ .icon {
287
+ height: 16px;
288
+ width: 16px;
289
+ margin-left: var(--o-gap-2);
290
+ }
291
+ }
292
+
293
+ .content-container-mobile {
294
+ margin-top: var(--o-gap-3);
295
+
296
+ &:last-child {
297
+ margin-bottom: 12px;
298
+ }
299
+
300
+ .content-subtitle {
301
+ color: var(--o-color-info1);
302
+ display: flex;
303
+ align-items: center;
304
+ @include text2;
305
+ }
306
+
307
+ .content-tag {
308
+ margin-left: var(--o-gap-2);
309
+ --layout-pkg-radius: var(--o-radius-xs);
310
+ }
311
+
312
+ .desc-container {
313
+ overflow: hidden;
314
+ position: relative;
315
+
316
+ .item-desc {
317
+ color: var(--o-color-info2);
318
+ margin-top: var(--o-gap-1);
319
+ text-align: justify;
320
+ word-break: normal;
321
+ @include text1;
322
+ @include text-truncate(2);
323
+ }
324
+ }
325
+ }
326
+ }
327
+
328
+ .header-tool {
329
+ position: absolute;
330
+ bottom: 36px;
331
+ left: 0;
332
+ width: 99px;
333
+
334
+ display: flex;
335
+ height: auto;
336
+ justify-content: center;
337
+ align-items: center;
338
+ flex-direction: column;
339
+ }
340
+
341
+ .header-tool-code {
342
+ width: 99px;
343
+ @include nav-item;
344
+ @include text1;
345
+ }
346
+ </style>