@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,354 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ OCard,
4
+ ODivider,
5
+ OIcon,
6
+ OIconSearch,
7
+ OInput, OPagination,
8
+ ORadio,
9
+ ORadioGroup,
10
+ OTag,
11
+ OToggle,
12
+ } from '@opensig/opendesign';
13
+ import { computed, ref } from 'vue';
14
+ import { type EventsCardItemT, EventsStatusT, type EventsListPropsT, SearchParamsT } from './types';
15
+ import { compareDate } from './utils.ts';
16
+ import { useI18n } from '@/i18n';
17
+
18
+ import { CITY_MAP, DEFAULT_COVER } from './config.ts';
19
+ import { useScreen } from '@opendesign-plus/composables';
20
+
21
+ const { t } = useI18n();
22
+ const { lePadV } = useScreen();
23
+
24
+ const props = withDefaults(
25
+ defineProps<EventsListPropsT>(),
26
+ {
27
+ data: () => [],
28
+ },
29
+ );
30
+
31
+ interface StatusOptionT {
32
+ label: string;
33
+ value: EventsStatusT;
34
+ }
35
+
36
+ const statusOptions: StatusOptionT[] = [
37
+ {
38
+ label: t('events.statusAll'),
39
+ value: EventsStatusT.ALL,
40
+ },
41
+ {
42
+ label: t('events.statusIng'),
43
+ value: EventsStatusT.ING,
44
+ },
45
+ {
46
+ label: t('events.statusFinish'),
47
+ value: EventsStatusT.FINISH,
48
+ },
49
+ ];
50
+
51
+ defineSlots<{
52
+ empty?: () => any;
53
+ }>();
54
+
55
+ const emits = defineEmits<{
56
+ (e: 'search', params: SearchParamsT): void;
57
+ }>();
58
+ const status = ref<EventsStatusT>(EventsStatusT.ALL);
59
+ const input = ref('');
60
+ const keyword = ref('');
61
+
62
+ const emitSearch = (params = {}) => {
63
+ emits(
64
+ 'search',
65
+ Object.assign(
66
+ {
67
+ page: props.page,
68
+ pageSize: props.pageSize,
69
+ status: status.value,
70
+ keyword: keyword.value,
71
+ },
72
+ params,
73
+ ),
74
+ );
75
+ };
76
+
77
+ const changeStatus = () => {
78
+ emitSearch();
79
+ };
80
+ const changeKeyword = () => {
81
+ keyword.value = input.value;
82
+ emitSearch();
83
+ };
84
+ const list = computed(() => {
85
+ return props.data
86
+ .map((v: EventsCardItemT) => {
87
+ return {
88
+ ...v,
89
+ status: !compareDate(new Date(), v.date as string) ? EventsStatusT.ING : EventsStatusT.FINISH,
90
+ };
91
+ })
92
+ .sort((a: EventsCardItemT, b: EventsCardItemT) => (compareDate(a.date as string, b.date as string) ? -1 : 1))
93
+ .map((v) => {
94
+ const city = v.city?.replace('市', '')?.replace('中国', '')?.replaceAll(' ', '');
95
+ let cover = null;
96
+
97
+ if (Array.isArray(CITY_MAP[city])) {
98
+ cover = CITY_MAP[city][v.name.length % CITY_MAP[city].length];
99
+ } else {
100
+ cover = CITY_MAP[city];
101
+ }
102
+ if (!cover) {
103
+ cover = DEFAULT_COVER;
104
+ }
105
+ return {
106
+ ...v,
107
+ cover,
108
+ };
109
+ });
110
+ });
111
+ </script>
112
+
113
+ <template>
114
+ <div class="o-events-list">
115
+ <div class="filter-wrapper">
116
+ <div class="filter-left">
117
+ <span>{{ t('events.status') }}</span>
118
+ <ORadioGroup v-model="status" :style="{ '--radio-group-gap': '8px' }" @change="changeStatus">
119
+ <ORadio v-for="t in statusOptions" :key="t.value" :value="t.value">
120
+ <template #radio="{ checked }">
121
+ <OToggle :checked="checked">{{ t.label }}</OToggle>
122
+ </template>
123
+ </ORadio>
124
+ </ORadioGroup>
125
+ </div>
126
+ <OInput
127
+ v-model="input"
128
+ :placeholder="t('events.searchPlaceholder')"
129
+ @pressEnter="changeKeyword"
130
+ @clear="changeKeyword"
131
+ clearable>
132
+ <template #prefix>
133
+ <OIcon class="input-icon">
134
+ <OIconSearch />
135
+ </OIcon>
136
+ </template>
137
+ </OInput>
138
+ </div>
139
+ <div class="list-content">
140
+ <OCard v-for="item in list" :key="item.name" :cover="item.cover" :href="item.link">
141
+ <OTag class="event-status">
142
+ {{ item.status === EventsStatusT.ING ? t('events.statusIng') : t('events.statusFinish') }}
143
+ </OTag>
144
+ <div class="event-name">{{ item.name }}</div>
145
+ <div class="event-desc">
146
+ <div class="event-date">{{ item.date }}</div>
147
+ <ODivider direction="v" />
148
+ <div class="event-location" v-if="item.city">{{ item.city }}</div>
149
+ </div>
150
+ </OCard>
151
+ </div>
152
+ <template v-if="!list.length">
153
+ <slot name="empty"></slot>
154
+ </template>
155
+ <OPagination
156
+ v-if="total > 8"
157
+ :page="page"
158
+ :simple="lePadV"
159
+ :show-total="true"
160
+ :pageSize="pageSize"
161
+ :total="total"
162
+ @change="emitSearch"
163
+ :pageSizes="[4, 12, 24, 36, 48]"
164
+ />
165
+ </div>
166
+ </template>
167
+
168
+ <style lang="scss">
169
+ .o-events-list {
170
+ .filter-wrapper {
171
+ display: flex;
172
+ align-items: center;
173
+ flex-wrap: wrap;
174
+ justify-content: space-between;
175
+ background-color: var(--o-color-fill2);
176
+ border-radius: var(--o-radius-xs);
177
+ padding: var(--o-gap-5) var(--o-gap-6);
178
+ gap: var(--o-gap-3) var(--o-gap-2);
179
+ @include text1;
180
+
181
+ .filter-left {
182
+ display: flex;
183
+ align-items: center;
184
+ gap: var(--o-gap-2);
185
+ flex-wrap: wrap;
186
+
187
+ span:first-child {
188
+ flex-shrink: 0;
189
+ margin-right: var(--o-gap-5);
190
+ font-weight: 500;
191
+ @include respond-to('pad_v') {
192
+ margin-right: var(--o-gap-4);
193
+ }
194
+ @include respond-to('phone') {
195
+ margin-right: var(--o-gap-4);
196
+ }
197
+ }
198
+
199
+ .o-toggle {
200
+ --toggle-size: 32px;
201
+ --toggle-padding: 3px 15px;
202
+ --toggle-radius: 4px;
203
+ max-height: 32px;
204
+ --toggle-bg-color: var(--o-color-fill1);
205
+ --toggle-bg-color-hover: var(--o-color-control2-light);
206
+ --toggle-color: var(--o-color-info1);
207
+ --toggle-color-hover: var(--o-color-info1);
208
+ --toggle-color-active: var(--o-color-primary1);
209
+ --toggle-color-disabled: var(--o-color-info4);
210
+ @include text1;
211
+ }
212
+ }
213
+
214
+ .o-input {
215
+ .o-icon-search {
216
+ font-size: 24px;
217
+ @include respond-to('<=pad_v') {
218
+ font-size: 16px;
219
+ }
220
+ }
221
+ }
222
+ }
223
+ .list-content {
224
+ display: grid;
225
+ grid-template-columns: repeat(4, 1fr);
226
+ gap: var(--o-gap-6);
227
+ margin-top: var(--o-gap-6);
228
+ @include respond-to('<=pad_v') {
229
+ grid-template-columns: repeat(1, 1fr);
230
+ }
231
+ @include respond-to('pad_v') {
232
+ margin-top: var(--o-gap-4);
233
+ gap: var(--o-gap-3);
234
+ }
235
+ @include respond-to('phone') {
236
+ margin-top: var(--o-gap-4);
237
+ gap: var(--o-gap-3);
238
+ }
239
+
240
+ .o-card {
241
+ aspect-ratio: 1 / 1;
242
+ position: relative;
243
+ @include respond-to('<=pad_v') {
244
+ aspect-ratio: 1 / 0.4;
245
+ }
246
+
247
+ .o-card-cover {
248
+ padding: 0;
249
+ }
250
+
251
+ .o-card-content {
252
+ display: flex;
253
+ flex-direction: column;
254
+ align-items: center;
255
+ justify-content: center;
256
+ position: absolute;
257
+ overflow: hidden; // 防止内容溢出
258
+ box-sizing: border-box; // 确保 padding 计入总尺寸
259
+ left: 0;
260
+ top: 0;
261
+ width: 100%;
262
+ height: 100%;
263
+ color: var(--o-color-white);
264
+ text-align: center;
265
+ cursor: pointer;
266
+ padding: var(--o-gap-6);
267
+ z-index: 10;
268
+
269
+ @include respond-to('pad_v') {
270
+ margin-top: var(--o-gap-4);
271
+ }
272
+ @include respond-to('phone') {
273
+ margin-top: var(--o-gap-4);
274
+ }
275
+
276
+ .event-status {
277
+ --tag-color: rgb(var(--o-white));
278
+ --tag-bg-color: rgba(var(--o-black), 0.25);
279
+ --tag-padding: var(--o-gap-1) var(--o-gap-3);
280
+ border: none;
281
+ position: absolute;
282
+ top: var(--o-gap-3);
283
+ right: var(--o-gap-3);
284
+ border-radius: var(--o-radius-xs);
285
+ @include respond-to('<=pad_v') {
286
+ --tag-padding: var(--o-gap-1);
287
+ }
288
+ }
289
+
290
+ .event-name {
291
+ font-weight: 500;
292
+ text-align: center;
293
+ height: 3lh; // 3倍行高
294
+ @include h2;
295
+ @include text-truncate(3);
296
+ @include respond-to('pad_v') {
297
+ @include h1;
298
+ }
299
+ @include respond-to('phone') {
300
+ height: 2lh;
301
+ @include text-truncate(2);
302
+ }
303
+ }
304
+
305
+ .event-desc {
306
+ text-align: center;
307
+ font-weight: 500;
308
+ margin-top: var(--o-gap-5);
309
+
310
+ .o-divider {
311
+ --o-divider-color: var(--o-color-info1-inverse);
312
+ --o-divider-bd-color: var(--o-color-info1-inverse);
313
+ display: none;
314
+ }
315
+
316
+ @include text1;
317
+ @include respond-to('pad_v') {
318
+ margin-top: var(--o-gap-2);
319
+ }
320
+ @include respond-to('phone') {
321
+ margin-top: var(--o-gap-2);
322
+ }
323
+ @include respond-to('<=pad_v') {
324
+ display: flex;
325
+ align-items: center;
326
+ .o-divider {
327
+ display: block;
328
+ }
329
+ @include tip1;
330
+ }
331
+ }
332
+ }
333
+ }
334
+
335
+ .event-card {
336
+ border-radius: var(--o-radius-xs);
337
+ color: rgb(var(--o-white));
338
+ background-size: cover;
339
+ background-repeat: no-repeat;
340
+ }
341
+ }
342
+
343
+ .o-pagination {
344
+ margin-top: var(--o-gap-6);
345
+ --pagination-item-bg-color-current: var(--o-color-primary1);
346
+ --pagination-item-color-current: #fff;
347
+
348
+ .o-pagination-wrap {
349
+ justify-content: flex-end;
350
+ }
351
+ }
352
+
353
+ }
354
+ </style>
@@ -0,0 +1,35 @@
1
+ import IconSummit from '~icons/events/icon-summit.svg';
2
+ import IconEvents from '~icons/events/icon-events.svg';
3
+ import IconCompetition from '~icons/events/icon-competition.svg';
4
+ import IconRelease from '~icons/events/icon-release.svg';
5
+
6
+ export const EVENTS_COLOR_MAP = {
7
+ summit: '--o-orange-6',
8
+ events: '--o-cyan-6',
9
+ competition: '--o-blue-6',
10
+ release: '--o-purple-6',
11
+ };
12
+
13
+ export const EVENTS_ICON_MAP = {
14
+ events: IconEvents,
15
+ competition: IconCompetition,
16
+ release: IconRelease,
17
+ summit: IconSummit,
18
+ };
19
+
20
+ export const CITY_MAP = {
21
+ 上海: 'https://infrastructure-website.osinfra.cn/picture/city/shanghai.jpg',
22
+ 北京: 'https://infrastructure-website.osinfra.cn/picture/city/beijing.jpg',
23
+ 南京: 'https://infrastructure-website.osinfra.cn/picture/city/nanjing.jpg',
24
+ 天津: 'https://infrastructure-website.osinfra.cn/picture/city/tianjin.jpg',
25
+ 成都: 'https://infrastructure-website.osinfra.cn/picture/city/chengdu.jpg',
26
+ 无锡: 'https://infrastructure-website.osinfra.cn/picture/city/wuxi.jpg',
27
+ 杭州: 'https://infrastructure-website.osinfra.cn/picture/city/hangzhou.jpg',
28
+ 深圳: ['https://infrastructure-website.osinfra.cn/picture/city/shenzhen1.jpg', 'https://infrastructure-website.osinfra.cn/picture/city/shenzhen2.jpg'],
29
+ 苏州: 'https://infrastructure-website.osinfra.cn/picture/city/suzhou.jpg',
30
+ 西安: 'https://infrastructure-website.osinfra.cn/picture/city/xian.jpg',
31
+ 郑州: 'https://infrastructure-website.osinfra.cn/picture/city/zhengzhou.jpg',
32
+ 武汉: 'https://infrastructure-website.osinfra.cn/picture/city/wuhan.jpg',
33
+ };
34
+
35
+ export const DEFAULT_COVER = 'https://infrastructure-website.osinfra.cn/picture/city/default-cover.jpg';
@@ -0,0 +1,24 @@
1
+ import _OEventsCalendar from './OEventsCalendar.vue';
2
+ import _OEventsList from './OEventsList.vue';
3
+ import _OEventsApply from './OEventsApply.vue';
4
+ import type { App } from 'vue';
5
+
6
+
7
+ const OEventsCalendar = Object.assign(_OEventsCalendar, {
8
+ install(app: App) {
9
+ app.component('OEventsCalendar', _OEventsCalendar);
10
+ },
11
+ });
12
+ const OEventsList = Object.assign(_OEventsList, {
13
+ install(app: App) {
14
+ app.component('OEventsList', _OEventsList);
15
+ },
16
+ });
17
+ const OEventsApply = Object.assign(_OEventsApply, {
18
+ install(app: App) {
19
+ app.component('OEventsApply', _OEventsApply);
20
+ },
21
+ });
22
+
23
+ export { OEventsCalendar, OEventsList, OEventsApply };
24
+ export * from './types';
@@ -0,0 +1,80 @@
1
+ type EventsTextAlignT = 'center' | 'left';
2
+
3
+ export enum EventsStatusT {
4
+ FINISH = 'finish',
5
+ ING = 'ing',
6
+ ALL = ''
7
+ }
8
+
9
+
10
+ export interface EventsItemT {
11
+ name: string; // 事件名称
12
+ date: string | [string, string]; // 事件日期, "YYYY/MM/DD" 或 ["YYYY/MM/DD", "YYYY/MM/DD"]
13
+ location?: string; // 事件地点
14
+ link?: string; // 跳转链接
15
+ linkProps?: {
16
+ [key: string]: string | boolean;
17
+ },
18
+ align?: EventsTextAlignT; // 文本居中方式
19
+ cover?: string; // 事件背景,作为列表卡片形式时使用
20
+ status?: EventsStatusT; // 事件状态,作为列表卡片形式时使用,不传递,组件内部通过date计算得出
21
+ }
22
+
23
+ export type EventsTypeT = 'summit' | 'events' | 'competition' | 'release';
24
+
25
+ export interface CalendarItemT {
26
+ name: string; // 分组标题
27
+ desc?: string; // 分组描述,可选,支持传递html片段
28
+ type: EventsTypeT; // 分组类型,决定颜色和图标
29
+ color?: string; // 分组颜色,可选,如果没有传递由type决定, RGB格式: "255, 0, 0",包括图标背景和事件背景
30
+ icon?: string; // 分组图标,可选,如果没有传递由type决定,白色线性,背景由颜色决定
31
+ data: EventsItemT[];
32
+ isSpanMonth?: boolean; // 是否包含跨月事件,为true时date需要是[string, string]
33
+ }
34
+
35
+ export interface StepItemT {
36
+ title: string; // 标题
37
+ desc?: string; // 描述,支持HTML片段
38
+ img?: string; // 插图
39
+ imgPhone?: string; // 移动端插图
40
+ listTitle?: string; // 列表标题
41
+ list: Array<{
42
+ title: string; // 列表项标题
43
+ desc?: string; // 列表项描述
44
+ }>;
45
+ }
46
+
47
+ // 活动列表
48
+ export interface EventsCardItemT {
49
+ name: string; // 事件名称
50
+ date: string; // 事件日期
51
+ city: string; // 事件城市
52
+ cover?: string; // 卡片封面,如果不传递,组件内部通过date计算得出
53
+ status?: EventsStatusT; // 事件状态,不传递,组件内部通过date计算得出
54
+ link: string; // 跳转链接
55
+ }
56
+
57
+
58
+ // 组件 Props 类型定义
59
+ export interface EventsApplyPropsT {
60
+ steps: StepItemT[];
61
+ }
62
+
63
+ export interface EventsListPropsT {
64
+ data: EventsCardItemT[]; // 活动列表数据
65
+ page: number; // 当前页码
66
+ pageSize: number; // 当前每页个数
67
+ total: number; // 活动总计个数
68
+ }
69
+
70
+ export interface EventsCalendarPropsT {
71
+ data: CalendarItemT[];
72
+ }
73
+
74
+ // OEventList 组件搜索事件参数
75
+ export interface SearchParamsT {
76
+ page: number; // 页码
77
+ pageSize: number; // 每页数量
78
+ status: EventsStatusT; // 状态
79
+ keyword: string; // 关键词
80
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 比较两个日期字符串的先后顺序
3
+ * @param dateA - 第一个日期字符串
4
+ * @param dateB - 第二个日期字符串
5
+ * @returns 如果 dateA 晚于 dateB 返回 true,否则返回 false
6
+ */
7
+ export const compareDate = (dateA: string | Date, dateB: string | Date): boolean => {
8
+ return new Date(dateA).getTime() > new Date(dateB).getTime();
9
+ };
@@ -0,0 +1,175 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue';
3
+
4
+ import ContentWrapper from '../common/ContentWrapper.vue';
5
+ import HeaderNav from './components/HeaderNav.vue';
6
+ import HeaderContent from './components/HeaderContent.vue';
7
+ import HeaderUbmcNav from './components/HeaderUbmcNav.vue';
8
+
9
+ import { useTheme } from '@opendesign-plus/composables';
10
+
11
+ const { isDark } = useTheme();
12
+
13
+ export interface OHeaderT {
14
+ (e: 'go-home'): void;
15
+ (e: 'handle-click', val: any): void;
16
+ }
17
+
18
+ const emit = defineEmits<OHeaderT>();
19
+
20
+ const props = defineProps({
21
+ logo: undefined,
22
+ lang: undefined,
23
+ community: undefined,
24
+ navData: undefined,
25
+ bgLeft: undefined,
26
+ bgRight: undefined,
27
+ tagMap: undefined,
28
+ activeIndex: undefined,
29
+ });
30
+
31
+ const hoverIndex = ref();
32
+ const hoverId = ref();
33
+ const itemData = ref();
34
+ const itemVisible = ref(false);
35
+
36
+ const goHome = () => {
37
+ emit('go-home');
38
+ };
39
+ const handleMouseenter = (val: any) => {
40
+ itemData.value = val;
41
+ hoverIndex.value = val.id;
42
+ if (val?.children?.length) {
43
+ itemVisible.value = true;
44
+ }
45
+ };
46
+ const handleMouseleave = (val: any) => {
47
+ itemVisible.value = false;
48
+ };
49
+ const handleClick = (val: any) => {
50
+ emit('handle-click', val);
51
+ };
52
+
53
+ const handleMouseenterSub = (val: string) => {
54
+ hoverId.value = val;
55
+ };
56
+ const handleMouseleaveSub = (val: string) => {
57
+ hoverId.value = val;
58
+ };
59
+ </script>
60
+
61
+ <template>
62
+ <div class="header">
63
+ <div class="header-wrap" :class="{ 'header-wrap-dark': isDark }">
64
+ <ContentWrapper class="header-content">
65
+ <!-- logo -->
66
+ <div class="header-logo" @click="goHome">
67
+ <slot name="logo">
68
+ <img v-if="props.logo" class="logo" alt="logo" :src="props.logo" />
69
+ </slot>
70
+ </div>
71
+ <!-- nav -->
72
+ <div v-if="props.community !== 'openUBMC'" class="header-nav">
73
+ <slot name="nav">
74
+ <HeaderNav
75
+ v-if="props.navData"
76
+ :nav-data="props.navData"
77
+ :hoverId="hoverId"
78
+ :active-index="props.activeIndex"
79
+ @handle-mouseenter="handleMouseenter"
80
+ @handle-mouseleave="handleMouseleave"
81
+ @handle-click="handleClick"
82
+ ></HeaderNav>
83
+ </slot>
84
+ </div>
85
+ <!-- openUBMC nav -->
86
+ <div v-if="props.community === 'openUBMC'" class="header-nav-openubmc">
87
+ <slot name="nav">
88
+ <HeaderUbmcNav v-if="props.navData" :nav-data="props.navData" :has-perm="true" :tag-map="props.tagMap" />
89
+ </slot>
90
+ </div>
91
+ <!-- toolbar -->
92
+ <div v-if="$slots.toolbar" class="header-toolbar">
93
+ <slot name="toolbar"></slot>
94
+ </div>
95
+ </ContentWrapper>
96
+ </div>
97
+ <div v-if="props.community !== 'openUBMC'" class="header-nav-content">
98
+ <HeaderContent
99
+ :itemData="itemData"
100
+ :item-visible="itemVisible"
101
+ :bg-left="props.bgLeft"
102
+ :bg-right="props.bgRight"
103
+ :community="props.community"
104
+ :hover-index="hoverIndex"
105
+ @handle-mouseenter-sub="handleMouseenterSub"
106
+ @handle-mouseleave-sub="handleMouseleaveSub"
107
+ ></HeaderContent>
108
+ </div>
109
+ </div>
110
+ </template>
111
+
112
+ <style lang="scss" scoped>
113
+ .header {
114
+ --o-header-height: 72px;
115
+ }
116
+ .header-wrap {
117
+ background-color: var(--o-color-fill2);
118
+ position: fixed;
119
+ left: 0;
120
+ right: 0;
121
+ top: 0;
122
+ z-index: 999;
123
+ box-shadow: 0 3px 9px 0 rgba(0, 18, 85, 0.08);
124
+ backdrop-filter: blur(5px);
125
+ height: var(--o-header-height);
126
+ }
127
+ .header-content {
128
+ display: flex;
129
+ align-items: center;
130
+ height: 100%;
131
+ }
132
+ .header-logo {
133
+ height: 100%;
134
+ display: flex;
135
+ align-items: center;
136
+ cursor: pointer;
137
+ margin-right: 24px;
138
+ flex-shrink: 0;
139
+ }
140
+ .logo {
141
+ height: 32px;
142
+ }
143
+ .header-nav {
144
+ flex: 1;
145
+ height: 100%;
146
+ min-width: 0;
147
+ overflow: hidden;
148
+ position: relative;
149
+ }
150
+ .header-nav-openubmc {
151
+ flex: 1;
152
+ height: 100%;
153
+ min-width: 0;
154
+ }
155
+ .header-toolbar {
156
+ height: 100%;
157
+ }
158
+ .header-nav-content {
159
+ position: fixed;
160
+ top: var(--o-header-height);
161
+ left: 0;
162
+ right: 0;
163
+ background: var(--o-color-fill2);
164
+ z-index: 998;
165
+ box-shadow: 0 3px 9px 0 rgba(0, 18, 85, 0.08);
166
+ overflow: hidden;
167
+ }
168
+
169
+ .header-wrap-dark {
170
+ box-shadow: 0 3px 9px 0 rgba(var(--o-mixedgray-4), 0.08);
171
+ .header-nav-content {
172
+ box-shadow: 0 3px 9px 0 rgba(var(--o-mixedgray-4), 0.08);
173
+ }
174
+ }
175
+ </style>