@opendesign-plus/components 0.0.1-rc.2 → 0.0.1-rc.21

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