@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,389 @@
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
+ import dayjs from 'dayjs';
21
+
22
+ const { t } = useI18n();
23
+ const { lePadV } = useScreen();
24
+
25
+ const props = withDefaults(
26
+ defineProps<EventsListPropsT>(),
27
+ {
28
+ data: () => [],
29
+ },
30
+ );
31
+
32
+ interface StatusOptionT {
33
+ label: string;
34
+ value: EventsStatusT;
35
+ }
36
+
37
+ const statusOptions: StatusOptionT[] = [
38
+ {
39
+ label: t('events.statusAll'),
40
+ value: EventsStatusT.ALL,
41
+ },
42
+ {
43
+ label: t('events.statusIng'),
44
+ value: EventsStatusT.ING,
45
+ },
46
+ {
47
+ label: t('events.statusFinish'),
48
+ value: EventsStatusT.FINISH,
49
+ },
50
+ ];
51
+
52
+ defineSlots<{
53
+ empty?: () => any;
54
+ }>();
55
+
56
+ const emits = defineEmits<{
57
+ (e: 'search', params: SearchParamsT): void;
58
+ }>();
59
+ const status = ref<EventsStatusT>(EventsStatusT.ALL);
60
+ const input = ref('');
61
+ const keyword = ref('');
62
+
63
+ const emitSearch = (params = {}) => {
64
+ emits(
65
+ 'search',
66
+ Object.assign(
67
+ {
68
+ page: props.page,
69
+ pageSize: props.pageSize,
70
+ status: status.value,
71
+ keyword: keyword.value,
72
+ },
73
+ params,
74
+ ),
75
+ );
76
+ };
77
+
78
+ const changeStatus = () => {
79
+ emitSearch();
80
+ };
81
+ const changeKeyword = () => {
82
+ keyword.value = input.value;
83
+ emitSearch();
84
+ };
85
+ const list = computed(() => {
86
+ return props.data
87
+ .map((v: EventsCardItemT) => {
88
+ let startDate = v.startDate;
89
+ let endDate = v.endDate;
90
+ let dateStr = dayjs(v.date).format('YYYY/MM/DD');
91
+ if (startDate && endDate) {
92
+ const yearFirstDay = dayjs().format('YYYY-01-01');
93
+ if (compareDate(yearFirstDay, startDate)) {
94
+ startDate = yearFirstDay;
95
+ }
96
+ const yearLastDay = dayjs().format('YYYY-12-31');
97
+ if (compareDate(endDate, yearLastDay)) {
98
+ endDate = yearLastDay;
99
+ }
100
+ dateStr = `${ dayjs(startDate).format('YYYY/MM/DD') }-${ dayjs(endDate).format('MM/DD') }`;
101
+ }
102
+ return {
103
+ ...v,
104
+ startDate,
105
+ endDate,
106
+ dateStr,
107
+ status: !compareDate(new Date(), v.date || v.endDate as string) ? EventsStatusT.ING : EventsStatusT.FINISH,
108
+
109
+ };
110
+ })
111
+ .sort((a: EventsCardItemT, b: EventsCardItemT) => (compareDate(a.date || a.endDate as string, b.date || b.endDate as string) ? -1 : 1))
112
+ .map((v) => {
113
+ const city = v.city?.replace('市', '')?.replace('中国', '')?.replaceAll(' ', '');
114
+ let cover = null;
115
+
116
+ if (Array.isArray(CITY_MAP[city])) {
117
+ cover = CITY_MAP[city][v.name.length % CITY_MAP[city].length];
118
+ } else {
119
+ cover = CITY_MAP[city];
120
+ }
121
+ if (!cover) {
122
+ cover = DEFAULT_COVER;
123
+ }
124
+ return {
125
+ ...v,
126
+ cover,
127
+ };
128
+ });
129
+ });
130
+ </script>
131
+
132
+ <template>
133
+ <div class="o-events-list">
134
+ <div class="filter-wrapper">
135
+ <div class="filter-left">
136
+ <span>{{ t('events.status') }}</span>
137
+ <ORadioGroup v-model="status" :style="{ '--radio-group-gap': '8px' }" @change="changeStatus">
138
+ <ORadio v-for="t in statusOptions" :key="t.value" :value="t.value">
139
+ <template #radio="{ checked }">
140
+ <OToggle :checked="checked">{{ t.label }}</OToggle>
141
+ </template>
142
+ </ORadio>
143
+ </ORadioGroup>
144
+ </div>
145
+ <OInput
146
+ v-model="input"
147
+ :placeholder="t('events.searchPlaceholder')"
148
+ @pressEnter="changeKeyword"
149
+ @clear="changeKeyword"
150
+ clearable>
151
+ <template #prefix>
152
+ <OIcon class="input-icon">
153
+ <OIconSearch />
154
+ </OIcon>
155
+ </template>
156
+ </OInput>
157
+ </div>
158
+ <div class="list-content">
159
+ <OCard v-for="item in list" :key="item.name" :cover="item.cover" :href="item.link">
160
+ <OTag class="event-status">
161
+ {{ item.status === EventsStatusT.ING ? t('events.statusIng') : t('events.statusFinish') }}
162
+ </OTag>
163
+ <div class="event-name">{{ item.name }}</div>
164
+ <div class="event-desc">
165
+ <div class="event-date">{{ item.dateStr }}</div>
166
+ <ODivider direction="v" />
167
+ <div class="event-location" v-if="item.city">{{ item.city }}</div>
168
+ </div>
169
+ </OCard>
170
+ </div>
171
+ <template v-if="!list.length">
172
+ <slot name="empty"></slot>
173
+ </template>
174
+ <OPagination
175
+ v-if="total > 8"
176
+ :page="page"
177
+ :simple="lePadV"
178
+ :show-total="true"
179
+ :pageSize="pageSize"
180
+ :total="total"
181
+ @change="emitSearch"
182
+ :pageSizes="[4, 12, 24, 36, 48]"
183
+ />
184
+ </div>
185
+ </template>
186
+
187
+ <style lang="scss">
188
+ .o-events-list {
189
+ .filter-wrapper {
190
+ display: flex;
191
+ align-items: center;
192
+ flex-wrap: wrap;
193
+ justify-content: space-between;
194
+ background-color: var(--o-color-fill2);
195
+ border-radius: var(--o-radius-xs);
196
+ padding: var(--o-gap-5) var(--o-gap-6);
197
+ gap: var(--o-gap-3) var(--o-gap-2);
198
+ @include text1;
199
+ @include respond-to('<=pad_v') {
200
+ padding: var(--o-gap-3) var(--o-gap-4);
201
+ }
202
+
203
+ .filter-left {
204
+ display: flex;
205
+ align-items: center;
206
+ gap: var(--o-gap-2);
207
+ flex-wrap: wrap;
208
+
209
+ span:first-child {
210
+ flex-shrink: 0;
211
+ margin-right: var(--o-gap-5);
212
+ font-weight: 500;
213
+ @include respond-to('pad_v') {
214
+ margin-right: var(--o-gap-4);
215
+ }
216
+ @include respond-to('phone') {
217
+ margin-right: var(--o-gap-4);
218
+ }
219
+ }
220
+
221
+ .o-toggle {
222
+ --toggle-size: 32px;
223
+ --toggle-padding: 3px 15px;
224
+ --toggle-radius: 4px;
225
+ max-height: 32px;
226
+ --toggle-bg-color: var(--o-color-fill1);
227
+ --toggle-bg-color-hover: var(--o-color-control2-light);
228
+ --toggle-color: var(--o-color-info1);
229
+ --toggle-color-hover: var(--o-color-info1);
230
+ --toggle-color-active: var(--o-color-primary1);
231
+ --toggle-color-disabled: var(--o-color-info4);
232
+ @include text1;
233
+ }
234
+ }
235
+
236
+ .o-input {
237
+ .o-icon-search {
238
+ font-size: 24px;
239
+ @include respond-to('<=pad_v') {
240
+ font-size: 16px;
241
+ }
242
+ }
243
+ }
244
+ }
245
+ .list-content {
246
+ display: grid;
247
+ grid-template-columns: repeat(4, 1fr);
248
+ gap: var(--o-gap-6);
249
+ margin-top: var(--o-gap-6);
250
+ @include respond-to('<=pad_v') {
251
+ grid-template-columns: repeat(1, 1fr);
252
+ container-type: inline-size;
253
+ }
254
+ @include respond-to('pad_v') {
255
+ margin-top: var(--o-gap-4);
256
+ gap: var(--o-gap-3);
257
+ }
258
+ @include respond-to('phone') {
259
+ margin-top: var(--o-gap-4);
260
+ gap: var(--o-gap-3);
261
+ }
262
+
263
+ .o-card {
264
+ aspect-ratio: 1 / 1;
265
+ position: relative;
266
+ @include respond-to('<=pad_v') {
267
+ aspect-ratio: 1 / 0.4;
268
+ }
269
+ @container (max-width: 300px) {
270
+ height: 140px;
271
+ width: 100%;
272
+ aspect-ratio: unset;
273
+ }
274
+
275
+ .o-card-cover {
276
+ padding: 0;
277
+ height: 100%;
278
+ }
279
+
280
+ .o-card-main {
281
+ padding: 0;
282
+ position: absolute;
283
+ overflow: hidden; // 防止内容溢出
284
+ box-sizing: border-box; // 确保 padding 计入总尺寸
285
+ left: 0;
286
+ top: 0;
287
+ width: 100%;
288
+ height: 100%;
289
+ }
290
+ .o-card-content {
291
+ position: absolute;
292
+ top: 0;
293
+ left: 0;
294
+ right: 0;
295
+ bottom: 0;
296
+ display: flex;
297
+ flex-direction: column;
298
+ align-items: center;
299
+ justify-content: center;
300
+ color: var(--o-color-white);
301
+ text-align: center;
302
+ padding: var(--o-gap-6);
303
+
304
+ @include respond-to('pad_v') {
305
+ margin-top: var(--o-gap-4);
306
+ }
307
+ @include respond-to('phone') {
308
+ margin-top: var(--o-gap-4);
309
+ }
310
+
311
+ .event-status {
312
+ --tag-color: rgb(var(--o-white));
313
+ --tag-bg-color: rgba(var(--o-black), 0.25);
314
+ --tag-padding: var(--o-gap-1) var(--o-gap-3);
315
+ border: none;
316
+ position: absolute;
317
+ top: var(--o-gap-3);
318
+ right: var(--o-gap-3);
319
+ border-radius: var(--o-radius-xs);
320
+ @include respond-to('<=pad_v') {
321
+ --tag-padding: var(--o-gap-1);
322
+ }
323
+ }
324
+
325
+ .event-name {
326
+ font-weight: 500;
327
+ text-align: center;
328
+ height: 3lh; // 3倍行高
329
+ @include h2;
330
+ @include text-truncate(3);
331
+ @include respond-to('pad_v') {
332
+ @include h1;
333
+ }
334
+ @include respond-to('phone') {
335
+ height: 2lh;
336
+ @include text-truncate(2);
337
+ }
338
+ }
339
+
340
+ .event-desc {
341
+ text-align: center;
342
+ font-weight: 500;
343
+ margin-top: var(--o-gap-5);
344
+
345
+ .o-divider {
346
+ --o-divider-color: var(--o-color-info1-inverse);
347
+ --o-divider-bd-color: var(--o-color-info1-inverse);
348
+ display: none;
349
+ }
350
+
351
+ @include text1;
352
+ @include respond-to('pad_v') {
353
+ margin-top: var(--o-gap-2);
354
+ }
355
+ @include respond-to('phone') {
356
+ margin-top: var(--o-gap-2);
357
+ }
358
+ @include respond-to('<=pad_v') {
359
+ display: flex;
360
+ align-items: center;
361
+ .o-divider {
362
+ display: block;
363
+ }
364
+ @include tip1;
365
+ }
366
+ }
367
+ }
368
+ }
369
+
370
+ .event-card {
371
+ border-radius: var(--o-radius-xs);
372
+ color: rgb(var(--o-white));
373
+ background-size: cover;
374
+ background-repeat: no-repeat;
375
+ }
376
+ }
377
+
378
+ .o-pagination {
379
+ margin-top: var(--o-gap-6);
380
+ --pagination-item-bg-color-current: var(--o-color-primary1);
381
+ --pagination-item-color-current: #fff;
382
+
383
+ .o-pagination-wrap {
384
+ justify-content: flex-end;
385
+ }
386
+ }
387
+
388
+ }
389
+ </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: Record<string, string | string[]> = {
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,83 @@
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
+ startDate?: string; // 事件开始日期
52
+ endDate?: string; // 事件结束日期
53
+ dateStr?: string; // 经处理后的展示时间
54
+ city: string; // 事件城市
55
+ cover?: string; // 卡片封面,如果不传递,组件内部通过date计算得出
56
+ status?: EventsStatusT; // 事件状态,不传递,组件内部通过date计算得出
57
+ link: string; // 跳转链接
58
+ }
59
+
60
+
61
+ // 组件 Props 类型定义
62
+ export interface EventsApplyPropsT {
63
+ steps: StepItemT[];
64
+ }
65
+
66
+ export interface EventsListPropsT {
67
+ data: EventsCardItemT[]; // 活动列表数据
68
+ page: number; // 当前页码
69
+ pageSize: number; // 当前每页个数
70
+ total: number; // 活动总计个数
71
+ }
72
+
73
+ export interface EventsCalendarPropsT {
74
+ data: CalendarItemT[];
75
+ }
76
+
77
+ // OEventList 组件搜索事件参数
78
+ export interface SearchParamsT {
79
+ page: number; // 页码
80
+ pageSize: number; // 每页数量
81
+ status: EventsStatusT; // 状态
82
+ keyword: string; // 关键词
83
+ }
@@ -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,157 @@
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
+
8
+ import { type NavT } from './types.ts';
9
+
10
+ import { useTheme } from '@opendesign-plus/composables';
11
+
12
+ const { isDark } = useTheme();
13
+
14
+ export interface OHeaderT {
15
+ (e: 'go-home'): void;
16
+ (e: 'handle-click', val: any): void;
17
+ }
18
+
19
+ const emit = defineEmits<OHeaderT>();
20
+
21
+ const props = defineProps<NavT>();
22
+
23
+ const hoverIndex = ref();
24
+ const hoverId = ref();
25
+ const itemData = ref();
26
+ const itemVisible = ref(false);
27
+
28
+ const goHome = () => {
29
+ emit('go-home');
30
+ };
31
+ const handleMouseenter = (val: any) => {
32
+ itemData.value = val;
33
+ hoverIndex.value = val.id;
34
+ if (val?.children?.length) {
35
+ itemVisible.value = true;
36
+ }
37
+ };
38
+ const handleMouseleave = (val: any) => {
39
+ itemVisible.value = false;
40
+ };
41
+ const handleClick = (val: any) => {
42
+ emit('handle-click', val);
43
+ };
44
+
45
+ const handleMouseenterSub = (val: string) => {
46
+ hoverId.value = val;
47
+ };
48
+ const handleMouseleaveSub = (val: string) => {
49
+ hoverId.value = val;
50
+ };
51
+ </script>
52
+
53
+ <template>
54
+ <div class="header">
55
+ <div class="header-wrap" :class="{ 'header-wrap-dark': isDark }">
56
+ <ContentWrapper class="header-content">
57
+ <!-- logo -->
58
+ <div class="header-logo" @click="goHome">
59
+ <slot name="logo">
60
+ <img v-if="props.logo" class="logo" alt="logo" :src="props.logo" />
61
+ </slot>
62
+ </div>
63
+ <!-- nav -->
64
+ <div class="header-nav">
65
+ <slot name="nav">
66
+ <HeaderNav
67
+ v-if="props.navData"
68
+ :nav-data="props.navData"
69
+ :hoverId="hoverId"
70
+ :active-index="props.activeIndex"
71
+ @handle-mouseenter="handleMouseenter"
72
+ @handle-mouseleave="handleMouseleave"
73
+ @handle-click="handleClick"
74
+ ></HeaderNav>
75
+ </slot>
76
+ </div>
77
+ <!-- toolbar -->
78
+ <div v-if="$slots.toolbar" class="header-toolbar">
79
+ <slot name="toolbar"></slot>
80
+ </div>
81
+ </ContentWrapper>
82
+ </div>
83
+ <div class="header-nav-content">
84
+ <HeaderContent
85
+ :itemData="itemData"
86
+ :item-visible="itemVisible"
87
+ :bg-left="props.bgLeft"
88
+ :bg-right="props.bgRight"
89
+ :community="props.community"
90
+ :hover-index="hoverIndex"
91
+ @handle-mouseenter-sub="handleMouseenterSub"
92
+ @handle-mouseleave-sub="handleMouseleaveSub"
93
+ ></HeaderContent>
94
+ </div>
95
+ </div>
96
+ </template>
97
+
98
+ <style lang="scss" scoped>
99
+ .header {
100
+ --o-header-height: 72px;
101
+ }
102
+ .header-wrap {
103
+ background-color: var(--o-color-fill2);
104
+ position: fixed;
105
+ left: 0;
106
+ right: 0;
107
+ top: 0;
108
+ z-index: 999;
109
+ box-shadow: 0 3px 9px 0 rgba(0, 18, 85, 0.08);
110
+ backdrop-filter: blur(5px);
111
+ height: var(--o-header-height);
112
+ }
113
+ .header-content {
114
+ display: flex;
115
+ align-items: center;
116
+ height: 100%;
117
+ }
118
+ .header-logo {
119
+ height: 100%;
120
+ display: flex;
121
+ align-items: center;
122
+ cursor: pointer;
123
+ margin-right: 24px;
124
+ flex-shrink: 0;
125
+ }
126
+ .logo {
127
+ height: 32px;
128
+ }
129
+ .header-nav {
130
+ flex: 1;
131
+ height: 100%;
132
+ min-width: 0;
133
+ overflow: hidden;
134
+ position: relative;
135
+ }
136
+ .header-toolbar {
137
+ height: 100%;
138
+ position: relative;
139
+ }
140
+ .header-nav-content {
141
+ position: fixed;
142
+ top: var(--o-header-height);
143
+ left: 0;
144
+ right: 0;
145
+ background: var(--o-color-fill2);
146
+ z-index: 998;
147
+ box-shadow: 0 3px 9px 0 rgba(0, 18, 85, 0.08);
148
+ overflow: hidden;
149
+ }
150
+
151
+ .header-wrap-dark {
152
+ box-shadow: 0 3px 9px 0 rgba(var(--o-mixedgray-4), 0.08);
153
+ .header-nav-content {
154
+ box-shadow: 0 3px 9px 0 rgba(var(--o-mixedgray-4), 0.08);
155
+ }
156
+ }
157
+ </style>