@opendesign-plus/components 0.0.1-rc.3 → 0.0.1-rc.30

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 (266) hide show
  1. package/dist/chunk-OElCookieNotice.cjs.js +1 -0
  2. package/dist/chunk-OElCookieNotice.es.js +862 -0
  3. package/dist/components/activity/OActivityApproval.vue.d.ts +273 -0
  4. package/dist/components/activity/OActivityForm.vue.d.ts +138 -0
  5. package/dist/components/activity/OActivityMyCalendar.vue.d.ts +636 -0
  6. package/dist/components/activity/composables/useActivityConfig.d.ts +17 -0
  7. package/dist/components/activity/config.d.ts +1 -0
  8. package/dist/components/activity/index.d.ts +648 -0
  9. package/dist/components/activity/types.d.ts +88 -0
  10. package/dist/components/banner/OBanner.vue.d.ts +13 -0
  11. package/dist/components/banner/OBannerContent.vue.d.ts +7 -0
  12. package/dist/components/banner/index.d.ts +68 -0
  13. package/dist/components/banner/types.d.ts +31 -0
  14. package/dist/components/config-provider/OPlusConfigProvider.vue.d.ts +24 -0
  15. package/dist/components/config-provider/index.d.ts +30 -0
  16. package/dist/components/cookie-notice/OCookieNotice.vue.d.ts +17 -0
  17. package/dist/components/cookie-notice/index.d.ts +53 -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 +14 -0
  24. package/dist/components/events/index.d.ts +78 -0
  25. package/dist/components/events/types.d.ts +73 -0
  26. package/dist/components/events/utils.d.ts +7 -0
  27. package/dist/components/footer/OFooter.vue.d.ts +46 -0
  28. package/dist/components/footer/index.d.ts +89 -0
  29. package/dist/components/header/OHeader.vue.d.ts +30 -0
  30. package/dist/components/header/OHeaderMobile.vue.d.ts +178 -0
  31. package/dist/components/header/components/HeaderContent.vue.d.ts +13 -0
  32. package/dist/components/header/components/HeaderNav.vue.d.ts +19 -0
  33. package/dist/components/header/components/HeaderNavMobile.vue.d.ts +36 -0
  34. package/dist/components/header/index.d.ts +153 -0
  35. package/dist/components/header/types.d.ts +85 -0
  36. package/dist/components/header-language-switcher/OHeaderLanguageSwitcher.vue.d.ts +49 -0
  37. package/dist/components/header-language-switcher/index.d.ts +90 -0
  38. package/dist/components/header-search/OHeaderSearch.vue.d.ts +1032 -0
  39. package/dist/components/header-search/index.d.ts +607 -0
  40. package/dist/components/header-source-code/OHeaderSourceCode.vue.d.ts +18 -0
  41. package/dist/components/header-source-code/index.d.ts +23 -0
  42. package/dist/components/header-theme/OHeaderTheme.vue.d.ts +25 -0
  43. package/dist/components/header-theme/index.d.ts +50 -0
  44. package/dist/components/header-user/OHeaderUser.vue.d.ts +40 -0
  45. package/dist/components/header-user/index.d.ts +53 -0
  46. package/dist/components/meeting/OMeetingCalendar.vue.d.ts +297 -0
  47. package/dist/components/meeting/OMeetingForm.vue.d.ts +141 -0
  48. package/dist/components/meeting/OMeetingMyCalendar.vue.d.ts +644 -0
  49. package/dist/components/meeting/OMeetingPlayback.vue.d.ts +94 -0
  50. package/dist/components/meeting/OMeetingSigCalendar.vue.d.ts +24 -0
  51. package/dist/components/meeting/components/OMeetingCalendarList.vue.d.ts +29 -0
  52. package/dist/components/meeting/components/OMeetingDetail.vue.d.ts +13 -0
  53. package/dist/components/meeting/components/OMeetingPlaybackSubtitles.vue.d.ts +20 -0
  54. package/dist/components/meeting/components/OMeetingPlaybackVideo.vue.d.ts +17 -0
  55. package/dist/components/meeting/components/OMeetingSigAside.vue.d.ts +16 -0
  56. package/dist/components/meeting/composables/useMeetingConfig.d.ts +14 -0
  57. package/dist/components/meeting/config.d.ts +12 -0
  58. package/dist/components/meeting/index.d.ts +823 -0
  59. package/dist/components/meeting/types.d.ts +235 -0
  60. package/dist/components/meeting/utils.d.ts +9 -0
  61. package/dist/components/search/OSearchInput.vue.d.ts +1025 -0
  62. package/dist/components/search/composables/useImageSearch.d.ts +48 -0
  63. package/dist/components/search/composables/useKeywordHighlight.d.ts +2 -0
  64. package/dist/components/search/composables/useSearchHistory.d.ts +14 -0
  65. package/dist/components/search/index.d.ts +600 -0
  66. package/dist/components/search/internal/HighlightText.vue.d.ts +9 -0
  67. package/dist/components/{OHeaderSearch.vue.d.ts → search/internal/SearchImageInput.vue.d.ts} +210 -166
  68. package/dist/components/search/internal/SearchPanel.vue.d.ts +100 -0
  69. package/dist/components/search/types.d.ts +20 -0
  70. package/dist/components/{OSection.vue.d.ts → section/OSection.vue.d.ts} +4 -4
  71. package/dist/components/section/index.d.ts +47 -0
  72. package/dist/components.cjs.js +224 -1
  73. package/dist/components.css +1 -1
  74. package/dist/components.element.cjs.js +1 -0
  75. package/dist/components.element.es.js +4 -0
  76. package/dist/components.es.js +46234 -1078
  77. package/dist/index.d.ts +16 -12
  78. package/docs/design.md +27 -27
  79. package/docs/design_banner.md +41 -41
  80. package/docs/design_section.md +27 -27
  81. package/package.json +18 -9
  82. package/scripts/generate-components-index.js +61 -80
  83. package/src/assets/events/svg-icons/icon-checked.svg +3 -0
  84. package/src/assets/events/svg-icons/icon-competition.svg +7 -0
  85. package/src/assets/events/svg-icons/icon-events.svg +4 -0
  86. package/src/assets/events/svg-icons/icon-release.svg +4 -0
  87. package/src/assets/events/svg-icons/icon-summit.svg +4 -0
  88. package/src/assets/meeting/svg-icons/icon-all.svg +4 -0
  89. package/src/assets/meeting/svg-icons/icon-backward.svg +4 -0
  90. package/src/assets/meeting/svg-icons/icon-calendar.svg +3 -0
  91. package/src/assets/meeting/svg-icons/icon-cancel.svg +4 -0
  92. package/src/assets/meeting/svg-icons/icon-captions.svg +4 -0
  93. package/src/assets/meeting/svg-icons/icon-close-captions.svg +6 -0
  94. package/src/assets/meeting/svg-icons/icon-close-fullscreen.svg +6 -0
  95. package/src/assets/meeting/svg-icons/icon-copy.svg +3 -0
  96. package/src/assets/meeting/svg-icons/icon-create.svg +5 -0
  97. package/src/assets/meeting/svg-icons/icon-delete.svg +7 -0
  98. package/src/assets/meeting/svg-icons/icon-empty.svg +31 -0
  99. package/src/assets/meeting/svg-icons/icon-empty_dark.svg +49 -0
  100. package/src/assets/meeting/svg-icons/icon-event.svg +4 -0
  101. package/src/assets/meeting/svg-icons/icon-export.svg +3 -0
  102. package/src/assets/meeting/svg-icons/icon-forward.svg +4 -0
  103. package/src/assets/meeting/svg-icons/icon-fullscreen.svg +6 -0
  104. package/src/assets/meeting/svg-icons/icon-help.svg +3 -0
  105. package/src/assets/meeting/svg-icons/icon-important.svg +4 -0
  106. package/src/assets/meeting/svg-icons/icon-info.svg +3 -0
  107. package/src/assets/meeting/svg-icons/icon-meet.svg +4 -0
  108. package/src/assets/meeting/svg-icons/icon-meeting-message.svg +5 -0
  109. package/src/assets/meeting/svg-icons/icon-meeting.svg +4 -0
  110. package/src/assets/meeting/svg-icons/icon-play.svg +5 -0
  111. package/src/assets/meeting/svg-icons/icon-playing-tip.svg +7 -0
  112. package/src/assets/meeting/svg-icons/icon-playing.svg +5 -0
  113. package/src/assets/meeting/svg-icons/icon-question.svg +4 -0
  114. package/src/assets/meeting/svg-icons/icon-sound.svg +5 -0
  115. package/src/assets/meeting/svg-icons/icon-speaker.svg +3 -0
  116. package/src/assets/meeting/svg-icons/icon-summit.svg +4 -0
  117. package/src/assets/meeting/svg-icons/icon-telligent.svg +3 -0
  118. package/src/assets/meeting/svg-icons/icon-tip.svg +3 -0
  119. package/src/assets/meeting/svg-icons/icon-todo.svg +4 -0
  120. package/src/assets/meeting/transparent.png +0 -0
  121. package/src/assets/styles/element-plus.scss +235 -0
  122. package/src/assets/svg-icons/icon-arrow-left.svg +3 -0
  123. package/src/assets/svg-icons/icon-avatar-line.svg +3 -0
  124. package/src/assets/svg-icons/icon-caret-left.svg +3 -0
  125. package/src/assets/svg-icons/icon-caret-right.svg +3 -0
  126. package/src/assets/svg-icons/icon-chevron-down.svg +3 -0
  127. package/src/assets/svg-icons/icon-chevron-right.svg +3 -3
  128. package/src/assets/svg-icons/icon-chevron-up.svg +3 -0
  129. package/src/assets/svg-icons/icon-close.svg +3 -3
  130. package/src/assets/svg-icons/icon-delete-hover.svg +4 -0
  131. package/src/assets/svg-icons/icon-delete.svg +7 -3
  132. package/src/assets/svg-icons/icon-filter.svg +3 -0
  133. package/src/assets/svg-icons/icon-header-back.svg +3 -3
  134. package/src/assets/svg-icons/icon-header-delete.svg +3 -3
  135. package/src/assets/svg-icons/icon-header-menu.svg +3 -0
  136. package/src/assets/svg-icons/icon-header-person.svg +3 -0
  137. package/src/assets/svg-icons/icon-header-search.svg +4 -4
  138. package/src/assets/svg-icons/icon-image-close.svg +4 -0
  139. package/src/assets/svg-icons/icon-image-upload.svg +3 -0
  140. package/src/assets/svg-icons/icon-image-zoomin.svg +3 -0
  141. package/src/assets/svg-icons/icon-loading.svg +4 -0
  142. package/src/assets/svg-icons/icon-locale.svg +3 -0
  143. package/src/assets/svg-icons/icon-log-off.svg +3 -0
  144. package/src/assets/svg-icons/icon-message.svg +3 -0
  145. package/src/assets/svg-icons/icon-moon.svg +3 -3
  146. package/src/assets/svg-icons/icon-outlink.svg +3 -0
  147. package/src/assets/svg-icons/icon-overview.svg +3 -0
  148. package/src/assets/svg-icons/icon-refresh.svg +3 -0
  149. package/src/assets/svg-icons/icon-search.svg +3 -0
  150. package/src/assets/svg-icons/icon-setting.svg +3 -0
  151. package/src/assets/svg-icons/icon-sun.svg +3 -3
  152. package/src/assets/svg-icons/icon-tips.svg +3 -0
  153. package/src/components/activity/OActivityApproval.vue +868 -0
  154. package/src/components/activity/OActivityForm.vue +548 -0
  155. package/src/components/activity/OActivityMyCalendar.vue +1540 -0
  156. package/src/components/activity/composables/useActivityConfig.ts +141 -0
  157. package/src/components/activity/config.ts +1 -0
  158. package/src/components/activity/index.ts +24 -0
  159. package/src/components/activity/types.ts +95 -0
  160. package/src/components/banner/OBanner.vue +288 -0
  161. package/src/components/banner/OBannerContent.vue +175 -0
  162. package/src/components/banner/index.ts +18 -0
  163. package/src/components/banner/types.ts +39 -0
  164. package/src/components/common/AppAvatar.vue +83 -0
  165. package/src/components/common/ClientOnly.vue +13 -0
  166. package/src/components/common/ContentWrapper.vue +85 -85
  167. package/src/components/common/MoreText.vue +124 -0
  168. package/src/components/common/ThFilter.vue +330 -0
  169. package/src/components/{OPlusConfigProvider.vue → config-provider/OPlusConfigProvider.vue} +32 -32
  170. package/src/components/config-provider/index.ts +10 -0
  171. package/src/components/cookie-notice/OCookieNotice.vue +575 -0
  172. package/src/components/cookie-notice/index.ts +10 -0
  173. package/src/components/element-plus/OElCookieNotice.vue +603 -0
  174. package/src/components/element-plus/index.ts +3 -0
  175. package/src/components/events/OEventsApply.vue +503 -0
  176. package/src/components/events/OEventsCalendar.vue +600 -0
  177. package/src/components/events/OEventsList.vue +463 -0
  178. package/src/components/events/config.ts +35 -0
  179. package/src/components/events/index.ts +24 -0
  180. package/src/components/events/types.ts +84 -0
  181. package/src/components/events/utils.ts +9 -0
  182. package/src/components/footer/OFooter.vue +577 -0
  183. package/src/components/footer/index.ts +10 -0
  184. package/src/components/header/OHeader.vue +157 -0
  185. package/src/components/header/OHeaderMobile.vue +184 -0
  186. package/src/components/header/components/HeaderContent.vue +1125 -0
  187. package/src/components/header/components/HeaderNav.vue +278 -0
  188. package/src/components/header/components/HeaderNavMobile.vue +380 -0
  189. package/src/components/header/index.ts +18 -0
  190. package/src/components/header/types.ts +96 -0
  191. package/src/components/header-language-switcher/OHeaderLanguageSwitcher.vue +211 -0
  192. package/src/components/header-language-switcher/index.ts +10 -0
  193. package/src/components/header-search/OHeaderSearch.vue +628 -0
  194. package/src/components/header-search/index.ts +10 -0
  195. package/src/components/header-source-code/OHeaderSourceCode.vue +151 -0
  196. package/src/components/header-source-code/index.ts +10 -0
  197. package/src/components/header-theme/OHeaderTheme.vue +132 -0
  198. package/src/components/header-theme/index.ts +10 -0
  199. package/src/components/header-user/OHeaderUser.vue +238 -0
  200. package/src/components/header-user/index.ts +10 -0
  201. package/src/components/meeting/OMeetingCalendar.vue +909 -0
  202. package/src/components/meeting/OMeetingForm.vue +1131 -0
  203. package/src/components/meeting/OMeetingMyCalendar.vue +1536 -0
  204. package/src/components/meeting/OMeetingPlayback.vue +469 -0
  205. package/src/components/meeting/OMeetingSigCalendar.vue +439 -0
  206. package/src/components/meeting/components/OMeetingCalendarList.vue +609 -0
  207. package/src/components/meeting/components/OMeetingCalendarSelector.vue +213 -0
  208. package/src/components/meeting/components/OMeetingDetail.vue +263 -0
  209. package/src/components/meeting/components/OMeetingPlaybackSubtitles.vue +615 -0
  210. package/src/components/meeting/components/OMeetingPlaybackVideo.vue +741 -0
  211. package/src/components/meeting/components/OMeetingSigAside.vue +204 -0
  212. package/src/components/meeting/composables/useMeetingConfig.ts +108 -0
  213. package/src/components/meeting/config.ts +48 -0
  214. package/src/components/meeting/index.ts +45 -0
  215. package/src/components/meeting/types.ts +268 -0
  216. package/src/components/meeting/utils.ts +70 -0
  217. package/src/components/search/OSearchInput.vue +526 -0
  218. package/src/components/search/composables/useImageSearch.ts +157 -0
  219. package/src/components/search/composables/useKeywordHighlight.ts +30 -0
  220. package/src/components/search/composables/useSearchHistory.ts +75 -0
  221. package/src/components/search/index.ts +23 -0
  222. package/src/components/search/internal/HighlightText.vue +37 -0
  223. package/src/components/search/internal/SearchImageInput.vue +498 -0
  224. package/src/components/search/internal/SearchPanel.vue +431 -0
  225. package/src/components/search/types.ts +25 -0
  226. package/src/components/{OSection.vue → section/OSection.vue} +178 -178
  227. package/src/components/section/index.ts +10 -0
  228. package/src/draft/Banner.vue +265 -265
  229. package/src/draft/ButtonCards.vue +105 -105
  230. package/src/draft/Feature.vue +133 -133
  231. package/src/draft/Footer.vue +519 -512
  232. package/src/draft/HorizontalAnchor.vue +165 -165
  233. package/src/draft/ItemSwiper.vue +133 -133
  234. package/src/draft/Logo.vue +141 -141
  235. package/src/draft/LogoCard.vue +74 -74
  236. package/src/draft/LogoV2.vue +19 -19
  237. package/src/draft/MainCard.vue +38 -38
  238. package/src/draft/MultiCard.vue +94 -94
  239. package/src/draft/MultiIconCard.vue +73 -73
  240. package/src/draft/OInfoCard.vue +176 -176
  241. package/src/draft/Process.vue +81 -81
  242. package/src/draft/Section.vue +167 -167
  243. package/src/draft/SingleTabCard.vue +84 -84
  244. package/src/draft/SliderCard.vue +111 -110
  245. package/src/env.d.ts +16 -1
  246. package/src/i18n/en.ts +276 -20
  247. package/src/i18n/index.ts +56 -42
  248. package/src/i18n/zh.ts +266 -9
  249. package/src/index.ts +16 -32
  250. package/src/shared/provide.ts +6 -6
  251. package/src/shims-vue-dompurify-html.d.ts +17 -0
  252. package/src/vue.d.ts +9 -9
  253. package/tsconfig.json +37 -33
  254. package/vite.config.ts +123 -94
  255. package/dist/components/OBanner.vue.d.ts +0 -2
  256. package/dist/components/OCookieNotice.vue.d.ts +0 -16
  257. package/dist/components/OElCookieNotice.vue.d.ts +0 -31
  258. package/dist/components/OPlusConfigProvider.vue.d.ts +0 -23
  259. package/dist/components/OThemeSwitcher.vue.d.ts +0 -28
  260. package/dist/components.umd.js +0 -1
  261. package/src/components/OBanner.vue +0 -390
  262. package/src/components/OCookieNotice.vue +0 -424
  263. package/src/components/OElCookieNotice.vue +0 -413
  264. package/src/components/OHeaderSearch.vue +0 -601
  265. package/src/components/OThemeSwitcher.vue +0 -108
  266. package/src/components/common/ClientOnlyWrapper.ts +0 -21
@@ -0,0 +1,1540 @@
1
+ <script setup lang="ts">
2
+ import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue';
3
+ import {
4
+ OButton,
5
+ ODivider,
6
+ OIcon,
7
+ OScroller,
8
+ OCollapse,
9
+ OCollapseItem,
10
+ OTag,
11
+ ODialog,
12
+ useMessage,
13
+ OIconArrowLeft,
14
+ OIconArrowRight,
15
+ OIconChevronLeft,
16
+ OIconChevronRight,
17
+ DialogActionT, OLink,
18
+ } from '@opensig/opendesign';
19
+ import { ElCalendar } from 'element-plus';
20
+ import dayjs from 'dayjs';
21
+ import { useDebounceFn } from '@vueuse/core';
22
+
23
+ import IconCopy from '~icons/meeting/icon-copy.svg';
24
+
25
+ import type { ActivityItemT, MyActivityCalendarPropsT, ParamsItemT } from './types';
26
+ import { useScreen } from '@opendesign-plus/composables';
27
+ import { formatDate, getDateNumber } from '../meeting/utils';
28
+ import { useActivityConfig } from './composables/useActivityConfig';
29
+ import { CalendarDataType, MeetingItemT, PageParamsT } from '../meeting/types';
30
+ import OMeetingDetail from '@/components/meeting/components/OMeetingDetail.vue';
31
+ import { useI18n, Locales } from '@/i18n';
32
+ import { useMeetingConfig } from '@/components/meeting/composables/useMeetingConfig.ts';
33
+
34
+ const { t, locale } = useI18n();
35
+ const isZh = computed(() => locale.value === Locales.ZH);
36
+ const { statusMap, activityTypeMap } = useActivityConfig();
37
+ const { getConfig } = useMeetingConfig();
38
+
39
+ const formatMonthYear = (date: string | Date) => {
40
+ const d = dayjs(date || new Date());
41
+ return isZh.value ? d.format('YYYY MM月') : d.format('MMMM YYYY');
42
+ };
43
+
44
+ const message = useMessage(null);
45
+ const { isPhone } = useScreen();
46
+
47
+ const props = defineProps<MyActivityCalendarPropsT>();
48
+
49
+ const emits = defineEmits(['edit']);
50
+ const list = ref<ActivityItemT[]>([]); // 列表数据
51
+ const originList = ref<ActivityItemT[]>([]); // 原始数据
52
+
53
+ const currentPage = ref(1); // 分页-当前页
54
+ const pageSize = ref(50); // 分页-每页数量
55
+ const total = ref<number | null>(null); // 分页-总数
56
+ const reloadAll = ref(false); // 是否需要清空数据
57
+
58
+ const expanded = ref<number[]>([]); // 展开的数据,id
59
+
60
+ const nextLoading = ref(false);
61
+ const bottomReached = ref(false);
62
+
63
+ const canLoadMore = computed(() => total.value === null || originList.value.length < total.value);
64
+
65
+ const getList = async () => {
66
+ if (!props.getListRequest) {
67
+ return;
68
+ }
69
+ if (nextLoading.value) {
70
+ return;
71
+ }
72
+ try {
73
+ if (total.value !== null && total.value > 0 && (currentPage.value - 1) * pageSize.value > total.value) {
74
+ return;
75
+ }
76
+ // 当月数据已加载完,手动切换下一月
77
+ if (!canLoadMore.value && isPhone.value) {
78
+ changeMonth('next-month');
79
+ return;
80
+ }
81
+ nextLoading.value = true;
82
+ const res = await props.getListRequest({
83
+ page: currentPage.value,
84
+ size: pageSize.value,
85
+ start_date: selectedDate.value,
86
+ } as unknown as PageParamsT);
87
+ const tempList = (res.data || [])
88
+ .map((item: ActivityItemT) => {
89
+ const { start_date, end_date, start, end } = item;
90
+ return [
91
+ {
92
+ ...item,
93
+ time: `${ start_date }-${ end }`,
94
+ start_date_time: `${ start_date } ${ start }`,
95
+ end_date_time: `${ end_date } ${ end }`,
96
+ type: CalendarDataType.EVENTS,
97
+ dateRange: `${ start_date } ${ start }-${ end_date } ${ end }`,
98
+ isExpired: dayjs(`${ start_date } ${ start }`).isBefore(dayjs()),
99
+ },
100
+ ];
101
+ })
102
+ .flat()
103
+ .filter((v: ActivityItemT) => {
104
+ return v.start_date.slice(0, 7) === formatDate(selectedDate.value, 'YYYY-MM-DD').slice(0, 7);
105
+ });
106
+ if (reloadAll.value) {
107
+ originList.value = res.data || [];
108
+ list.value = tempList;
109
+ } else {
110
+ if (currentPage.value === 1 && !isPhone.value) {
111
+ originList.value = res.data || [];
112
+ list.value = tempList;
113
+ } else {
114
+ originList.value = [...originList.value, ...(res.data || [])];
115
+ list.value = [...list.value, ...tempList];
116
+ }
117
+ }
118
+ list.value.sort((a, b) => {
119
+ if (a.start_date === b.start_date) {
120
+ return getDateNumber(a.start) > getDateNumber(b.start) ? 1 : -1;
121
+ } else {
122
+ return dayjs(a.start_date).isAfter(dayjs(b.start_date)) ? 1 : -1;
123
+ }
124
+ });
125
+ total.value = res?.total || 0;
126
+ nextTick(() => {
127
+ getSelectedDate();
128
+ // 监听滚动事件以自动加载下一页
129
+ if (scrollerRef.value && !isPhone.value) {
130
+ updateScroller();
131
+ }
132
+ });
133
+ } finally {
134
+ nextLoading.value = false;
135
+ bottomReached.value = false;
136
+ reloadAll.value = false;
137
+ }
138
+ };
139
+
140
+ const expandList = ref<number[]>([]);
141
+ const getActivityDetail = (val: number) => {
142
+ if (!props.getActivityDetailRequest) {
143
+ return;
144
+ }
145
+ if (!expandList.value.includes(val)) {
146
+ expandList.value.push(val);
147
+ props.getActivityDetailRequest(val).then((res: ActivityItemT) => {
148
+ list.value?.forEach((item) => {
149
+ if (item.id === res.id) {
150
+ item.approve_record = res.approve_record;
151
+ }
152
+ });
153
+ });
154
+ }
155
+ };
156
+
157
+ const change = (val: (number | string)[]) => {
158
+ if (val.length) {
159
+ val.forEach((item) => {
160
+ getActivityDetail(item as unknown as number);
161
+ });
162
+ }
163
+ };
164
+
165
+ const calcIfApproved = (date: string) => {
166
+ const activityOfDate = list.value.filter((v) => v.start_date === date);
167
+ return activityOfDate.length && activityOfDate.every((v) => v.status === 3 || v.status === 4);
168
+ };
169
+
170
+ const scrollerScroll = (el: any) => {
171
+ const container = el.target;
172
+ if (!container) return;
173
+ const scrollTop = container.scrollTop; // 已经滚动的距离
174
+ const scrollHeight = container.scrollHeight; // 内容总高度
175
+ const clientHeight = container.clientHeight; // 容器可视高度
176
+ if (scrollTop + clientHeight >= scrollHeight) {
177
+ load();
178
+ }
179
+ };
180
+ const updateScroller = () => {
181
+ const scrollerContainerEl = scrollerRef.value.getContainerEl();
182
+ scrollerContainerEl.addEventListener('scroll', scrollerScroll);
183
+ };
184
+
185
+ // -------------------- 日历 --------------------
186
+ const calendarRef = ref();
187
+ const selectedDate = ref<any>(dayjs().format('YYYY-MM-DD'));
188
+ const allDateList = computed<string[]>(() => [...new Set(list.value.map((v) => v.start_date))].sort((a, b) => (dayjs(a).isBefore(dayjs(b)) ? -1 : 1)));
189
+ const dateList = computed<string[]>(() =>
190
+ [...new Set(list.value.filter((v) => !v.isExpired && !v.is_delete).map((v) => v.start_date))].sort((a, b) => (dayjs(a).isBefore(dayjs(b)) ? -1 : 1)),
191
+ );
192
+ const getSelectedDate = () => {
193
+ const latest = dateList.value.find((v) => !dayjs(v).isBefore(dayjs(new Date()).format('YYYY-MM-DD')));
194
+ if (latest) {
195
+ selectedDate.value = latest;
196
+ } else if (!selectedDate.value) {
197
+ selectedDate.value = dayjs().format('YYYY-MM-DD');
198
+ }
199
+ calendarRef.value?.pickDay(dayjs(selectedDate.value));
200
+ selectedDate.value = dayjs(selectedDate.value).format('YYYY-MM-DD');
201
+ // 根据天再计算出需要展开的最近的会议
202
+ const needExpand = list.value.find((v) => v.start_date === selectedDate.value && !v.isExpired && !v.is_delete);
203
+ if (needExpand) {
204
+ getActivityDetail(needExpand.id);
205
+ expanded.value = [needExpand.id];
206
+ }
207
+ };
208
+
209
+ const cellClick = (e: PointerEvent & any, clickable: boolean) => {
210
+ if (!clickable || !e.target?.className.includes('date-cell-text')) {
211
+ e.stopPropagation();
212
+ e.preventDefault();
213
+ }
214
+ };
215
+
216
+ const changeMonth = (val: string) => {
217
+ if (!calendarRef.value) return;
218
+ currentPage.value = 1;
219
+ total.value = null;
220
+ expandList.value = [];
221
+ window.scrollTo({
222
+ top: 0,
223
+ behavior: 'smooth',
224
+ });
225
+ calendarRef.value.selectDate(val);
226
+ reloadAll.value = true;
227
+ nextTick(() => {
228
+ selectedDate.value = dayjs(calendarRef.value.selectedDay).format('YYYY-MM-DD');
229
+ getList();
230
+ });
231
+ };
232
+
233
+
234
+ // -------------------- 活动列表 --------------------
235
+ interface ActivityListItemT {
236
+ start_date: string;
237
+ list: ActivityItemT[];
238
+ }
239
+
240
+ const activityList = computed<ActivityListItemT[]>(() => {
241
+ return list.value.reduce((prev: ActivityListItemT[], cur: ActivityItemT) => {
242
+ if (!prev.length) {
243
+ return [
244
+ {
245
+ start_date: cur.start_date,
246
+ list: [cur],
247
+ },
248
+ ];
249
+ } else {
250
+ const last = prev.at(-1);
251
+ if (last?.start_date === cur.start_date) {
252
+ last?.list.push(cur);
253
+ } else {
254
+ prev.push({
255
+ start_date: cur.start_date,
256
+ list: [cur],
257
+ });
258
+ }
259
+ return prev;
260
+ }
261
+ }, []);
262
+ });
263
+
264
+ // -------------------- 活动详情组件实例 --------------------
265
+ const detailRefs = ref<any>({});
266
+ const getDetailRefs = (insRef: any, id: number) => {
267
+ if (insRef && id) {
268
+ detailRefs.value[id] = insRef;
269
+ }
270
+ };
271
+ const copyInfo = async (idx: number) => {
272
+ const instance = detailRefs.value[idx];
273
+ await instance.copyInfo();
274
+ message.success({
275
+ content: t('common.copySuccess'),
276
+ });
277
+ };
278
+ // -------------------- 处理滚动事件 --------------------
279
+ const scrollerRef = ref();
280
+ const scrollToSelectedDate = (date: string) => {
281
+ const key = dayjs(date).format('YYYY-MM-DD');
282
+ const targetEle = document.querySelector(`#group-title-${ key }`);
283
+ if (targetEle) {
284
+ if (isPhone.value) {
285
+ window.scrollTo({
286
+ top: (targetEle.parentElement?.offsetTop || 0) - 52,
287
+ behavior: 'smooth',
288
+ });
289
+ } else {
290
+ scrollerRef.value?.scrollTo({
291
+ top: targetEle.parentElement?.offsetTop || 0,
292
+ behavior: 'smooth',
293
+ });
294
+ }
295
+ }
296
+ };
297
+
298
+ watch(
299
+ () => selectedDate.value,
300
+ () => {
301
+ scrollToSelectedDate(selectedDate.value);
302
+ },
303
+ );
304
+
305
+ // -------------------- 自动加载下一页 --------------------
306
+ const load = useDebounceFn(() => {
307
+ if (!canLoadMore.value) return;
308
+ if (isPhone.value) return;
309
+ bottomReached.value = true;
310
+ currentPage.value++;
311
+ getList();
312
+ }, 200);
313
+
314
+ // -------------------- 活动操作 --------------------
315
+ const dialogLoading = ref(false); // 弹窗按钮状态
316
+ const currentRow = ref<ActivityItemT | null>(null); // 当前活动详情
317
+ // 撤销审核
318
+ const revokeVisible = ref(false);
319
+ const handleRevokeItem = (val: ActivityItemT) => {
320
+ currentRow.value = val;
321
+ revokeVisible.value = true;
322
+ };
323
+ const confirm = () => {
324
+ if (!props.revokeActivityRequest) {
325
+ return;
326
+ }
327
+ if (!currentRow.value) {
328
+ return;
329
+ }
330
+ dialogLoading.value = true;
331
+ props.revokeActivityRequest(currentRow.value?.id)
332
+ .then((flag: any) => {
333
+ if (typeof flag === 'boolean' && !flag) {
334
+ return;
335
+ }
336
+ message.success({
337
+ content: t('meeting.revokeActivitySuccess', [currentRow.value?.title]),
338
+ });
339
+ reloadAll.value = true;
340
+ getList();
341
+ })
342
+ .finally(() => {
343
+ revokeVisible.value = false;
344
+ dialogLoading.value = false;
345
+ });
346
+ };
347
+ const cancel = () => {
348
+ revokeVisible.value = false;
349
+ };
350
+ // 修改活动
351
+ const handleEditItem = (val: ActivityItemT) => {
352
+ emits('edit', val);
353
+
354
+ };
355
+ // 提交审核
356
+ const handleSubmitReviewItem = (val: ActivityItemT) => {
357
+ if (!props.editActivityRequest) {
358
+ return;
359
+ }
360
+ const {
361
+ title,
362
+ start_date,
363
+ end_date,
364
+ register_end_date,
365
+ activity_type,
366
+ synopsis,
367
+ register_url,
368
+ content_url,
369
+ address,
370
+ start,
371
+ end,
372
+ approver,
373
+ } = val;
374
+ let params = {
375
+ title,
376
+ start_date,
377
+ end_date,
378
+ register_end_date,
379
+ activity_type,
380
+ synopsis,
381
+ register_url,
382
+ content_url,
383
+ address,
384
+ start,
385
+ end,
386
+ approver,
387
+ is_publish: 'true',
388
+ } as ParamsItemT;
389
+ props.editActivityRequest(val.id, params)
390
+ .then((flag: any) => {
391
+ if (typeof flag === 'boolean' && !flag) {
392
+ return;
393
+ }
394
+ message.success({
395
+ content: t('meeting.submitReviewSuccess', [val.title]),
396
+ });
397
+ reloadAll.value = true;
398
+ getList();
399
+ })
400
+ };
401
+ // 删除活动
402
+ const deleteVisible = ref(false);
403
+ const handleDeleteItem = (val: ActivityItemT) => {
404
+ currentRow.value = val;
405
+ deleteVisible.value = true;
406
+ };
407
+ const confirmDelete = () => {
408
+ if (!props.deleteActivityRequest) {
409
+ return;
410
+ }
411
+ dialogLoading.value = true;
412
+ props.deleteActivityRequest(currentRow.value?.id)
413
+ .then((flag: any) => {
414
+ if (typeof flag === 'boolean' && !flag) {
415
+ return;
416
+ }
417
+ message.success({
418
+ content: t('meeting.deleteActivitySuccess', [currentRow.value?.title]),
419
+ });
420
+ reloadAll.value = true;
421
+ getList();
422
+ })
423
+ .finally(() => {
424
+ deleteVisible.value = false;
425
+ dialogLoading.value = false;
426
+ });
427
+ };
428
+ const cancelDelete = () => {
429
+ deleteVisible.value = false;
430
+ };
431
+
432
+ // -------------------- 获取header高度 --------------------
433
+ const headerRef = ref();
434
+ const headerHeight = ref(0);
435
+ const getHeaderHeight = () => {
436
+ headerHeight.value = headerRef.value?.clientHeight || 0;
437
+ };
438
+
439
+ const handleScroll = useDebounceFn(() => {
440
+ if (!canLoadMore.value) return;
441
+ if (!isPhone.value) return;
442
+ const scrollPosition = window.scrollY || window.pageYOffset;
443
+ // 检测是否接近底部
444
+ const windowHeight = window.innerHeight;
445
+ const docHeight = document.documentElement.scrollHeight;
446
+ const distanceToBottom = docHeight - (scrollPosition + windowHeight);
447
+ // 当距离底部300px时开始加载
448
+ if (distanceToBottom <= 300 && !nextLoading.value) {
449
+ bottomReached.value = true;
450
+ // 加载下一页
451
+ currentPage.value++;
452
+ getList();
453
+ }
454
+ }, 200);
455
+
456
+ onMounted(() => {
457
+ getList();
458
+ // 添加滚动事件监听
459
+ window.addEventListener('scroll', handleScroll);
460
+ // 添加resize监听器
461
+ window.addEventListener('resize', handleScroll);
462
+ getHeaderHeight();
463
+ window.addEventListener('resize', getHeaderHeight);
464
+ });
465
+ onUnmounted(() => {
466
+ window.removeEventListener('scroll', handleScroll);
467
+ window.removeEventListener('resize', handleScroll);
468
+ window.removeEventListener('resize', getHeaderHeight);
469
+ const scrollerContainerEl = scrollerRef.value?.getContainerEl();
470
+ scrollerContainerEl?.removeEventListener('scroll', scrollerScroll);
471
+ });
472
+
473
+
474
+ const revokeActions = computed<DialogActionT[]>(() => {
475
+ return [{
476
+ id: 'confirm',
477
+ loading: dialogLoading.value,
478
+ color: 'primary',
479
+ variant: 'outline',
480
+ round: 'pill',
481
+ size: 'large',
482
+ label: t('meeting.confirmBtn'),
483
+ onClick: () => {
484
+ confirm();
485
+ },
486
+ }, {
487
+ id: 'cancel',
488
+ color: 'primary',
489
+ variant: 'solid',
490
+ round: 'pill',
491
+ size: 'large',
492
+ label: t('meeting.cancelBtn'),
493
+ onClick: () => {
494
+ cancel();
495
+ },
496
+ }];
497
+ });
498
+ const deleteActions = computed<DialogActionT[]>(() => {
499
+ return [{
500
+ id: 'confirm',
501
+ loading: dialogLoading.value,
502
+ color: 'primary',
503
+ variant: 'outline',
504
+ round: 'pill',
505
+ size: 'large',
506
+ label: t('meeting.confirmBtn'),
507
+ onClick: () => {
508
+ confirmDelete();
509
+ },
510
+ }, {
511
+ id: 'cancel',
512
+ color: 'primary',
513
+ variant: 'solid',
514
+ round: 'pill',
515
+ size: 'large',
516
+ label: t('meeting.cancelBtn'),
517
+ onClick: () => {
518
+ cancelDelete();
519
+ },
520
+ }];
521
+ });
522
+
523
+ </script>
524
+
525
+ <template>
526
+ <div class="o-my-activity-calendar">
527
+ <div class="activity-list">
528
+ <div v-if="isPhone" class="list-calendar-mb">
529
+ <span>{{ formatMonthYear(selectedDate) }}</span>
530
+ <span>
531
+ <OIcon @click="changeMonth('prev-month')"><OIconChevronLeft /></OIcon>
532
+ <OIcon @click="changeMonth('next-month')"><OIconChevronRight /></OIcon>
533
+ </span>
534
+ </div>
535
+ <div class="left-calendar">
536
+ <ElCalendar ref="calendarRef" v-model="selectedDate">
537
+ <template #header>
538
+ <span>{{ formatMonthYear(selectedDate) }}</span>
539
+ <div>
540
+ <OIcon @click="changeMonth('prev-month')">
541
+ <OIconChevronLeft />
542
+ </OIcon>
543
+ <OIcon @click="changeMonth('next-month')">
544
+ <OIconChevronRight />
545
+ </OIcon>
546
+ </div>
547
+ </template>
548
+ <template #date-cell="{ data }">
549
+ <div
550
+ @click="(e) => cellClick(e, allDateList.includes(data.day))"
551
+ :class="{
552
+ 'date-cell': true,
553
+ 'is-selected': data.isSelected,
554
+ 'is-today': formatDate(data.day) === formatDate(),
555
+ clickable: allDateList.includes(data.day),
556
+ approved: calcIfApproved(data.day),
557
+ }"
558
+ :style="{
559
+ '--dot-bg': `${getConfig(CalendarDataType.EVENTS, 'color')}`
560
+ }"
561
+ >
562
+ <div class="date-cell-text">
563
+ {{ Number(data.day.split('-')[2]) }}
564
+ </div>
565
+ </div>
566
+ </template>
567
+ </ElCalendar>
568
+ </div>
569
+ <div class="right-meeting">
570
+ <OScroller
571
+ v-if="list.length"
572
+ ref="scrollerRef"
573
+ @scrollend="load"
574
+ :style="{ '--header-height': headerHeight }"
575
+ show-type="hover"
576
+ class="scroller-container"
577
+ >
578
+ <div class="list-body">
579
+ <OCollapse v-model="expanded" :accordion="isPhone" @change="change">
580
+ <template v-for="(act, idx) in activityList" :key="act.start_date">
581
+ <div class="list-month-change prev-month" v-if="idx === 0" @click="changeMonth('prev-month')">
582
+ <OIcon>
583
+ <OIconArrowLeft />
584
+ </OIcon>
585
+ <span>{{ t('meeting.preMonth') }}</span>
586
+ </div>
587
+ <div class="act-item" :class="idx === activityList.length - 1 && 'last-item'">
588
+ <div
589
+ :class="{
590
+ 'act-bar': true,
591
+ 'is-active': dayjs(selectedDate).format('YYYY-MM-DD') === act.start_date,
592
+ 'is-end': act.list.every((row) => row.isExpired),
593
+ approved: act.list.every((row) => row.status === 3 || row.status === 4),
594
+ }"
595
+ >
596
+ <div class="act-bar-line"></div>
597
+ <div class="act-bar-dot"></div>
598
+ </div>
599
+ <div
600
+ :class="{
601
+ 'group-title': true,
602
+ 'is-end': act.list.every((row) => row.isExpired),
603
+ }"
604
+ :id="`group-title-${dayjs(new Date(act.start_date)).format('YYYY-MM-DD')}`"
605
+ >
606
+ {{ dayjs(act.start_date).format('MM/DD') }}
607
+ </div>
608
+ <OCollapseItem
609
+ v-for="(row, rowIdx) in act.list"
610
+ :key="row.sub_id || row.id"
611
+ :value="row.sub_id || row.id"
612
+ :class="{
613
+ 'last-item': idx === activityList.length - 1 && rowIdx === act.list.length - 1,
614
+ 'is-delete': row.is_delete,
615
+ 'is-end': row.isExpired,
616
+ }"
617
+ >
618
+ <template #title>
619
+ <div class="item-header-left">
620
+ <div
621
+ class="act-icon"
622
+ :style="{
623
+ backgroundColor: `${row.is_delete ? 'var(--o-color-info4)' : getConfig(CalendarDataType.EVENTS, 'color')}`
624
+ }"
625
+ >
626
+ <OIcon>
627
+ <component :is="getConfig(CalendarDataType.EVENTS, 'icon')" />
628
+ </OIcon>
629
+ </div>
630
+ <div class="header-info">
631
+ <div class="act-title">
632
+ <div class="title-text">{{ row.title }}</div>
633
+ <OTag
634
+ color="primary"
635
+ variant="outline"
636
+ :class="[`tag-${row.is_delete ? 'delete' : statusMap.get(row.status)?.id}`]">
637
+ {{
638
+ row.is_delete === 1 ? t('meeting.statusCanceled') : statusMap.get(row.status)?.text
639
+ }}
640
+ </OTag>
641
+ </div>
642
+ <div class="act-info">
643
+ <span class="date-range">{{ row.dateRange }}</span>
644
+ <ODivider direction="v"></ODivider>
645
+ <span>{{ activityTypeMap.get(row.activity_type)?.label }}</span>
646
+ </div>
647
+ </div>
648
+ </div>
649
+ <div class="item-header-right"
650
+ v-if="row.content_url && !row.is_delete && [3,4,5,6].includes(row.status)">
651
+ <OLink
652
+ :hover-underline="false"
653
+ v-if="row.content_url"
654
+ :href="row.content_url"
655
+ target="_blank"
656
+ rel="noopener noreferrer">
657
+ {{ t('meeting.activityDetail') }}
658
+ <template #suffix>
659
+ <OIcon>
660
+ <OIconChevronRight></OIconChevronRight>
661
+ </OIcon>
662
+ </template>
663
+ </OLink>
664
+ <OLink
665
+ :hover-underline="false"
666
+ v-if="
667
+ row.register_url && (
668
+ row.status === 3 ||
669
+ row.status === 4 ||
670
+ (row.status === 2 && row.update_activity_id && new Date(row.register_end_date).getTime() > new Date().getTime()))
671
+ "
672
+ :href="row.register_url"
673
+ target="_blank"
674
+ rel="noopener noreferrer"
675
+ >
676
+ {{ t('meeting.registerNow') }}
677
+ <template #suffix>
678
+ <OIcon>
679
+ <OIconChevronRight></OIconChevronRight>
680
+ </OIcon>
681
+ </template>
682
+ </OLink>
683
+ </div>
684
+ <OIcon @click.stop="() => copyInfo(rowIdx)" class="copy-icon">
685
+ <IconCopy />
686
+ </OIcon>
687
+ </template>
688
+ <div class="activity-detail">
689
+ <OMeetingDetail
690
+ :show="expanded.includes(row.id)"
691
+ :data="row as unknown as MeetingItemT"
692
+ :ref="(insRef) => getDetailRefs(insRef, row.id)"
693
+ />
694
+ <div class="activity-btn" v-if="!row.isExpired && !row.is_delete">
695
+ <OButton
696
+ v-if="row.status === 2"
697
+ variant="text"
698
+ @click="handleRevokeItem(row)"
699
+ >
700
+ {{ t('meeting.withdrawReview') }}
701
+ </OButton>
702
+ <OButton
703
+ v-if="row.status === 1 || row.status === 3 || row.status === 4 || row.status === 7"
704
+ variant="text" @click="handleEditItem(row)"
705
+ >
706
+ {{ t('meeting.modifyActivity') }}
707
+ </OButton>
708
+ <OButton
709
+ v-if="row.status === 1 || row.status === 7" variant="text"
710
+ @click="handleDeleteItem(row)"
711
+ >
712
+ {{ t('meeting.deleteActivity') }}
713
+ </OButton>
714
+ <OButton
715
+ v-if="row.status === 1 || row.status === 7" variant="text"
716
+ @click="handleSubmitReviewItem(row)"
717
+ >
718
+ {{ t('meeting.submitReview') }}
719
+ </OButton>
720
+ </div>
721
+ </div>
722
+ </OCollapseItem>
723
+ <div class="height-placeholder"></div>
724
+ </div>
725
+ <template v-if="idx === activityList.length - 1">
726
+ <div class="load-text" v-if="bottomReached">{{ t('meeting.loading') }}</div>
727
+ <div class="list-month-change next-month" @click="changeMonth('next-month')">
728
+ <OIcon>
729
+ <OIconArrowRight />
730
+ </OIcon>
731
+ <span>{{ t('meeting.nextMonth') }}</span>
732
+ </div>
733
+ </template>
734
+ </template>
735
+ </OCollapse>
736
+ </div>
737
+ </OScroller>
738
+ <slot v-else name="empty">
739
+ </slot>
740
+ </div>
741
+ </div>
742
+ </div>
743
+ <!-- 撤销审核弹窗 -->
744
+ <ODialog v-model:visible="revokeVisible" main-class="handle-dialog-active" :actions="revokeActions">
745
+ <template #header>{{ t('meeting.withdrawReview') }}</template>
746
+ <div class="dialog-content">{{ t('meeting.confirmRevokeActivity', [currentRow?.title]) }}</div>
747
+ </ODialog>
748
+ <!-- 删除活动弹窗 -->
749
+ <ODialog v-model:visible="deleteVisible" main-class="handle-dialog-active" :actions="deleteActions">
750
+ <template #header>{{ t('meeting.deleteActivity') }}</template>
751
+ <div class="dialog-content">{{ t('meeting.confirmDeleteActivity', [currentRow?.title]) }}</div>
752
+ </ODialog>
753
+ </template>
754
+
755
+ <style lang="scss">
756
+
757
+ .o-my-activity-calendar {
758
+ --activity-card-radius: var(--o-radius-xs);
759
+ --activity-cell-radius: var(--o-radius-xs);
760
+ height: 100%;
761
+ display: flex;
762
+ flex-direction: column;
763
+
764
+ .header {
765
+ display: flex;
766
+ align-items: center;
767
+ justify-content: space-between;
768
+ }
769
+
770
+ .title {
771
+ color: var(--o-color-info1);
772
+ font-weight: 500;
773
+ @include h2;
774
+ }
775
+
776
+ .desc {
777
+ color: var(--o-color-info2);
778
+ margin-top: 12px;
779
+ @include tip1;
780
+ }
781
+
782
+ .activity-list {
783
+ display: flex;
784
+ flex-wrap: nowrap;
785
+ gap: var(--o-gap-4);
786
+ height: 100%;
787
+ --phone-padding-top: 0;
788
+ @include respond('pad_v') {
789
+ flex-direction: column;
790
+ gap: var(--o-gap-4);
791
+ }
792
+ @include respond('phone') {
793
+ flex-direction: column;
794
+ gap: var(--o-gap-3);
795
+ --phone-padding-top: calc(var(--o-gap-5) + var(--o-gap-3) + var(--o-gap-3));
796
+ }
797
+
798
+ .o-loading {
799
+ .o-layer-mask {
800
+ background-color: transparent;
801
+ }
802
+
803
+ .o-loading-icon {
804
+ color: var(--layer-mask);
805
+ }
806
+ }
807
+ }
808
+
809
+ .list-calendar-mb {
810
+ align-items: center;
811
+ justify-content: space-between;
812
+ padding: 0 var(--grid--layout-padding);
813
+
814
+ span:first-child {
815
+ font-weight: 500;
816
+ @include display2;
817
+ }
818
+
819
+ span:last-child {
820
+ display: flex;
821
+ align-items: center;
822
+ }
823
+
824
+ .o-icon {
825
+ font-size: 24px;
826
+ cursor: pointer;
827
+
828
+ &:last-child {
829
+ margin-left: 24px;
830
+ }
831
+ }
832
+
833
+ @include respond('phone') {
834
+ padding-top: var(--o-gap-7);
835
+ background-color: var(--o-color-ubmc-bg);
836
+ padding-bottom: var(--o-gap-4);
837
+ --phone-padding-top: calc(28px + var(--o-gap-7) + var(--o-gap-4));
838
+ display: flex;
839
+ position: fixed;
840
+ height: var(--phone-padding-top);
841
+ z-index: 1;
842
+ top: var(--layout-header-height);
843
+ left: 0;
844
+ right: 0;
845
+ }
846
+ }
847
+
848
+ .left-calendar {
849
+ width: 336px;
850
+ flex-shrink: 0;
851
+ @include respond('pad_h') {
852
+ .el-calendar {
853
+ .el-calendar__body {
854
+ padding-left: 12px;
855
+ padding-right: 12px;
856
+
857
+ .el-calendar-table .date-cell {
858
+ height: 40px;
859
+ width: 28px;
860
+
861
+ .date-cell-text {
862
+ line-height: 24px;
863
+ @include tip2;
864
+ }
865
+ }
866
+ }
867
+ }
868
+ }
869
+ @include respond('pad_v') {
870
+ width: 100%;
871
+ }
872
+ @include respond('phone') {
873
+ display: none;
874
+ }
875
+
876
+ .el-calendar {
877
+ min-height: 460px;
878
+ height: 100%;
879
+ background-color: color-mix(in srgb, var(--o-color-control2-light) 40%, transparent);
880
+ border-radius: var(--activity-card-radius);
881
+
882
+ .el-calendar__header {
883
+ border-bottom: 1px solid var(--o-color-control4);
884
+
885
+ & > span {
886
+ font-weight: 500;
887
+ color: var(--o-color-info1);
888
+ @include h1;
889
+ }
890
+
891
+ & > div {
892
+ display: flex;
893
+ align-items: center;
894
+ gap: var(--o-gap-5);
895
+
896
+ .o-icon {
897
+ font-size: 24px;
898
+ cursor: pointer;
899
+
900
+ &:hover {
901
+ color: var(--o-color-primary1);
902
+ }
903
+ }
904
+ }
905
+ }
906
+
907
+ .el-calendar__body {
908
+ .el-calendar-table {
909
+ display: table;
910
+ width: 100%;
911
+
912
+ th {
913
+ text-align: center;
914
+ border: none;
915
+ --o-color-control3-light: transparent;
916
+ }
917
+
918
+ tr {
919
+ --o-color-fill2: transparent;
920
+ }
921
+
922
+ td {
923
+ border: none;
924
+ text-align: center;
925
+ transition: none;
926
+ padding: 0;
927
+ background-color: transparent !important;
928
+
929
+ .el-calendar-day {
930
+ padding: 0;
931
+ height: fit-content;
932
+ }
933
+
934
+ div {
935
+ cursor: default !important;
936
+ }
937
+
938
+ &:hover {
939
+ .el-calendar-day {
940
+ background-color: transparent;
941
+ }
942
+ }
943
+ }
944
+
945
+ .date-cell {
946
+ height: 56px;
947
+ width: 34px;
948
+ position: relative;
949
+ cursor: default !important;
950
+
951
+ .date-cell-text {
952
+ font-size: 14px;
953
+ line-height: 34px;
954
+ border-radius: var(--activity-cell-radius);
955
+ background-color: var(--o-color-control2-light);
956
+ border: 1px solid transparent;
957
+ }
958
+
959
+ .date-cell-text {
960
+ cursor: not-allowed !important;
961
+ }
962
+
963
+ &.clickable {
964
+ .date-cell-text {
965
+ cursor: pointer !important;
966
+ }
967
+
968
+ &:not(.is-selected) {
969
+ .date-cell-text:hover {
970
+ background-color: var(--o-color-control3-light);
971
+ }
972
+ }
973
+ }
974
+
975
+ &::after {
976
+ content: '';
977
+ position: absolute;
978
+ bottom: 5px;
979
+ left: 50%;
980
+ transform: translateX(-50%);
981
+ width: 8px;
982
+ height: 8px;
983
+ border-radius: 50%;
984
+ }
985
+
986
+ &.is-today {
987
+ .date-cell-text {
988
+ color: #000;
989
+ background-color: var(--o-color-control3-light);
990
+ }
991
+ }
992
+
993
+ &.is-selected {
994
+ .date-cell-text {
995
+ background-color: var(--o-color-control3-light);
996
+ border: 1px solid var(--o-color-primary1);
997
+ }
998
+ }
999
+
1000
+ &.clickable {
1001
+ &::after {
1002
+ background-color: rgb(var(--o-grey-6));
1003
+ }
1004
+
1005
+ &.approved::after {
1006
+ background-color: var(--dot-bg);
1007
+ }
1008
+
1009
+ &.expired::after {
1010
+ background-color: rgb(var(--o-grey-6));
1011
+ }
1012
+
1013
+ &.all-deleted::after {
1014
+ background-color: rgb(var(--o-grey-6));
1015
+ }
1016
+ }
1017
+ }
1018
+
1019
+ .is-today {
1020
+ color: inherit;
1021
+ }
1022
+ }
1023
+ }
1024
+ }
1025
+
1026
+
1027
+ }
1028
+
1029
+ .right-meeting {
1030
+ flex-grow: 1;
1031
+ background-color: var(--o-color-fill2);
1032
+
1033
+ @include respond('phone') {
1034
+ margin-top: calc(var(--phone-padding-top) - var(--o-gap-4));
1035
+ }
1036
+
1037
+ &.is-empty {
1038
+ display: flex;
1039
+ align-items: center;
1040
+ justify-content: center;
1041
+ min-height: 600px;
1042
+ }
1043
+
1044
+ .o-scroller {
1045
+ .o-scrollbar-rail {
1046
+ right: -16px;
1047
+ height: 100%;
1048
+ }
1049
+ }
1050
+
1051
+ .scroller-container {
1052
+ height: 100%;
1053
+ max-height: calc(var(--layout-left-height, 900px) - 4 * var(--o-gap-5) - var(--header-height) * 1px);
1054
+ @include respond('phone') {
1055
+ max-height: fit-content;
1056
+ }
1057
+
1058
+ .act-item {
1059
+ padding-left: 24px;
1060
+ position: relative;
1061
+
1062
+ &.last-item {
1063
+ flex-grow: 1;
1064
+ }
1065
+
1066
+ @include respond('phone') {
1067
+ padding-left: var(--o-gap-2);
1068
+ }
1069
+
1070
+ .act-bar {
1071
+ position: absolute;
1072
+ left: 0;
1073
+ width: 16px;
1074
+ top: 0;
1075
+ bottom: 0;
1076
+ overflow: hidden;
1077
+
1078
+ --active-color: var(--o-color-primary1);
1079
+
1080
+ &::before {
1081
+ content: '';
1082
+ width: 2px;
1083
+ position: absolute;
1084
+ top: 0;
1085
+ bottom: 0;
1086
+ left: 50%;
1087
+ transform: translateX(-50%);
1088
+ background-color: var(--o-color-control4);
1089
+ }
1090
+
1091
+ .act-bar-dot {
1092
+ width: 16px;
1093
+ height: 26px;
1094
+ position: relative;
1095
+ @include respond('laptop') {
1096
+ height: 24px;
1097
+ }
1098
+ @include respond('pad_h') {
1099
+ height: 22px;
1100
+ }
1101
+ @include respond('<=pad_v') {
1102
+ height: 22px;
1103
+ }
1104
+
1105
+ &::before,
1106
+ &::after {
1107
+ content: '';
1108
+ border-radius: 50%;
1109
+ position: absolute;
1110
+ top: 50%;
1111
+ left: 50%;
1112
+ transform: translateY(-50%) translateX(-50%);
1113
+ }
1114
+
1115
+ &::before {
1116
+ width: 16px;
1117
+ height: 16px;
1118
+ background-color: transparent;
1119
+ }
1120
+
1121
+ &::after {
1122
+ width: 8px;
1123
+ height: 8px;
1124
+ background-color: var(--active-color);
1125
+ }
1126
+ }
1127
+
1128
+ &.is-active {
1129
+ .act-bar-dot {
1130
+ &::before {
1131
+ background-color: var(--active-color);
1132
+ }
1133
+
1134
+ &::after {
1135
+ background-color: var(--o-color-fill2);
1136
+ }
1137
+ }
1138
+ }
1139
+
1140
+ &.is-end {
1141
+ --active-color: rgb(222, 222, 227);
1142
+ }
1143
+ }
1144
+
1145
+ .approved {
1146
+ --active-color: var(--o-color-primary1);
1147
+ }
1148
+
1149
+ .group-title {
1150
+ font-weight: 500;
1151
+ margin-bottom: var(--o-gap-2);
1152
+ color: var(--o-color-info1);
1153
+ @include text2;
1154
+ @include respond('phone') {
1155
+ padding-left: var(--o-gap-5);
1156
+ }
1157
+
1158
+ &.is-end {
1159
+ color: var(--o-color-info3);
1160
+ }
1161
+ }
1162
+ }
1163
+ }
1164
+ }
1165
+
1166
+ .list-body {
1167
+ height: 100%;
1168
+
1169
+ @include respond('phone') {
1170
+ height: fit-content;
1171
+ padding: var(--o-gap-4) !important;
1172
+ }
1173
+
1174
+ .list-month-change {
1175
+ flex-shrink: 0;
1176
+ display: flex;
1177
+ align-items: center;
1178
+ gap: var(--o-gap-5);
1179
+ cursor: pointer;
1180
+ --btn-color: var(--o-color-primary1);
1181
+ @include hover {
1182
+ --btn-color: var(--o-color-primary2);
1183
+ }
1184
+ @include respond('phone') {
1185
+ display: none;
1186
+ }
1187
+
1188
+ &.prev-month {
1189
+ margin-bottom: var(--o-gap-6);
1190
+ }
1191
+
1192
+ &.next-month {
1193
+ margin-top: var(--o-gap-6);
1194
+ padding-bottom: 32px;
1195
+ }
1196
+
1197
+ .o-icon {
1198
+ font-size: 24px;
1199
+ color: var(--btn-color);
1200
+ }
1201
+
1202
+ span {
1203
+ color: var(--btn-color);
1204
+ @include text1;
1205
+ }
1206
+ }
1207
+
1208
+ .o-collapse {
1209
+ padding: 0;
1210
+ border-radius: 0;
1211
+ height: 100%;
1212
+ display: flex;
1213
+ flex-direction: column;
1214
+
1215
+ .o-collapse-item-expanded + .o-collapse-item-expanded {
1216
+ margin-top: var(--o-gap-4);
1217
+ }
1218
+
1219
+ .height-placeholder {
1220
+ height: var(--o-gap-4);
1221
+ }
1222
+
1223
+ .o-collapse-item {
1224
+ padding: var(--o-gap-4) var(--o-gap-5);
1225
+ padding-bottom: calc(var(--o-gap-5) - var(--o-gap-4));
1226
+ border-top: none;
1227
+ border-radius: var(--activity-card-radius);
1228
+ transition: margin var(--o-easing-standard) var(--o-duration-s);
1229
+ --copy-display: none;
1230
+ --icon-size: 24px;
1231
+ @include respond('<=pad_v') {
1232
+ padding: var(--o-gap-3) var(--o-gap-4);
1233
+ }
1234
+
1235
+ @include respond('phone') {
1236
+ --icon-size: 20px;
1237
+ }
1238
+
1239
+ &:hover {
1240
+ .title-text {
1241
+ color: var(--o-color-primary1);
1242
+ }
1243
+ @include respond('>pad_v') {
1244
+ --copy-display: inline-flex;
1245
+ }
1246
+ }
1247
+
1248
+ &.is-delete,
1249
+ &.is-end {
1250
+
1251
+ .act-title {
1252
+ color: var(--o-color-info4);
1253
+
1254
+ .title-text {
1255
+ color: var(--o-color-info4);
1256
+ }
1257
+ }
1258
+ }
1259
+ &.o-collapse-item-expanded {
1260
+ border-bottom: none;
1261
+ background-color: color-mix(in srgb, var(--o-color-control2-light) 40%, transparent);
1262
+ @include respond('<=pad_v') {
1263
+ --copy-display: inline-flex;
1264
+ }
1265
+
1266
+ .o-collapse-item-header {
1267
+ border-bottom: 1px solid var(--o-color-control4);
1268
+ }
1269
+ }
1270
+ }
1271
+
1272
+ .o-collapse-item-header {
1273
+ border-bottom: none;
1274
+ padding-top: 0;
1275
+ padding-bottom: var(--o-gap-4);
1276
+ display: flex;
1277
+ align-items: center;
1278
+ gap: var(--o-gap-4);
1279
+ position: relative;
1280
+
1281
+ .o-collapse-item-icon {
1282
+ position: relative;
1283
+ top: 4px;
1284
+ flex-shrink: 0;
1285
+ @include respond('phone') {
1286
+ position: absolute;
1287
+ right: 0;
1288
+ width: 20px;
1289
+ height: 20px;
1290
+ font-size: 20px;
1291
+ bottom: var(--o-gap-2);
1292
+ top: revert;
1293
+ }
1294
+ }
1295
+
1296
+
1297
+ .o-collapse-item-title {
1298
+ flex: 1;
1299
+ width: 0;
1300
+ display: flex;
1301
+ flex-direction: column;
1302
+ align-items: flex-start;
1303
+ justify-content: space-between;
1304
+ margin-bottom: 0;
1305
+
1306
+ .item-header-left {
1307
+ display: flex;
1308
+ align-items: flex-start;
1309
+ gap: var(--o-gap-3);
1310
+ width: 100%;
1311
+ padding-right: 48px;
1312
+ @include respond('phone') {
1313
+ flex-grow: 1;
1314
+ width: 100%;
1315
+ align-self: stretch;
1316
+ flex-shrink: 0;
1317
+ }
1318
+
1319
+ .act-icon {
1320
+ width: var(--icon-size);
1321
+ height: var(--icon-size);
1322
+ border-radius: 50%;
1323
+ background-color: rgb(var(--o-cyan-6));
1324
+ color: #fff;
1325
+ display: flex;
1326
+ align-items: center;
1327
+ justify-content: center;
1328
+ flex-shrink: 0;
1329
+
1330
+ .o-icon {
1331
+ svg path {
1332
+ fill: currentColor;
1333
+ }
1334
+ }
1335
+
1336
+ }
1337
+
1338
+ .header-info {
1339
+ width: calc(100% - var(--o-gap-3) - var(--icon-size));
1340
+
1341
+ .act-title {
1342
+ font-weight: 500;
1343
+ display: flex;
1344
+ align-items: center;
1345
+ margin-bottom: var(--o-gap-2);
1346
+ @include text2;
1347
+
1348
+ &.is-delete,
1349
+ &.is-end {
1350
+ color: var(--o-color-info3);
1351
+ }
1352
+
1353
+ .title-text {
1354
+ flex: 0 1 auto;
1355
+ min-width: 0;
1356
+ max-width: 100%;
1357
+ @include text-truncate(1);
1358
+ }
1359
+
1360
+ .o-tag {
1361
+ margin-left: 8px;
1362
+ --tag-radius: var(--activity-cell-radius);
1363
+ font-weight: 500;
1364
+ padding: 0 8px;
1365
+ height: 24px;
1366
+ line-height: 24px !important;
1367
+ @include tip1;
1368
+
1369
+ .o-tag-label {
1370
+ transform: none !important;
1371
+ }
1372
+
1373
+ &.o-tag-outline {
1374
+ --tag-bd-color: transparent;
1375
+ --tag-color: #fff;
1376
+ }
1377
+
1378
+ &.tag-under-review {
1379
+ --tag-bg-color: rgb(var(--o-blue-6));
1380
+ }
1381
+
1382
+ &.tag-draft,
1383
+ &.tag-delete,
1384
+ &.tag-cancel {
1385
+ --tag-color: var(--o-color-info3);
1386
+ --tag-bg-color: var(--o-color-control1-light);
1387
+ }
1388
+
1389
+ &.tag-registration,
1390
+ &.tag-in-progress,
1391
+ &.tag-ended {
1392
+ --tag-bg-color: var(--o-color-success1);
1393
+ }
1394
+
1395
+ &.tag-reject {
1396
+ --tag-bg-color: var(--o-color-warning1);
1397
+ }
1398
+ }
1399
+ }
1400
+
1401
+ .act-info {
1402
+ color: var(--o-color-info3);
1403
+ display: flex;
1404
+ align-items: center;
1405
+ font-weight: 400;
1406
+ @include tip1;
1407
+
1408
+ .date-range {
1409
+ flex: 0 1 auto;
1410
+ min-width: 0;
1411
+ @include text-truncate(1);
1412
+ }
1413
+ }
1414
+ }
1415
+ }
1416
+
1417
+ .item-header-right {
1418
+ display: flex;
1419
+ align-items: center;
1420
+ padding-left: calc(var(--o-gap-3) + var(--icon-size));
1421
+ gap: var(--o-gap-4);
1422
+ margin-top: var(--o-gap-2);
1423
+ width: 100%;
1424
+ font-weight: 400;
1425
+
1426
+ .o-link {
1427
+ font-size: 14px;
1428
+ line-height: 21px;
1429
+ --link-color: var(--o-color-info2);
1430
+ --link-color-hover: var(--o-color-primary2);
1431
+ --link-color-active: var(--o-color-primary3);
1432
+ }
1433
+
1434
+ .o-icon {
1435
+ font-size: 16px;
1436
+ }
1437
+ }
1438
+
1439
+ .copy-icon {
1440
+ position: absolute;
1441
+ top: 50%;
1442
+ transform: translateY(-50%);
1443
+ right: calc(var(--collapse-item-icon-size) + var(--o-gap-4));
1444
+ font-size: 18px;
1445
+ height: 18px;
1446
+ width: 18px;
1447
+ display: var(--copy-display);
1448
+ color: var(--o-color-info1);
1449
+ @include respond('phone') {
1450
+ bottom: var(--o-gap-2);
1451
+ transform: revert;
1452
+ top: revert;
1453
+ right: calc(20px + var(--o-gap-2))
1454
+ }
1455
+
1456
+ &:hover {
1457
+ color: var(--o-color-primary1);
1458
+ }
1459
+
1460
+
1461
+ svg path {
1462
+ fill: currentColor;
1463
+ }
1464
+ }
1465
+ }
1466
+
1467
+ }
1468
+
1469
+ .o-collapse-item-body {
1470
+ margin-bottom: 0;
1471
+ padding: var(--o-gap-4) 0 0;
1472
+
1473
+ .activity-detail {
1474
+ padding-left: calc(var(--o-gap-3) + var(--icon-size));
1475
+ @include respond('phone') {
1476
+ padding-left: 0;
1477
+ }
1478
+
1479
+ .activity-btn {
1480
+ border-top: 1px solid var(--o-color-control4);
1481
+ margin-top: var(--o-gap-5);
1482
+ padding-top: var(--o-gap-4);
1483
+ display: flex;
1484
+ align-items: center;
1485
+ justify-content: flex-end;
1486
+ gap: var(--o-gap-5);
1487
+ }
1488
+ }
1489
+ }
1490
+
1491
+ .o-btn.o-btn-text {
1492
+ padding-left: 0 !important;
1493
+ padding-right: 0 !important;
1494
+ min-width: auto;
1495
+ }
1496
+
1497
+ .o-btn-text {
1498
+ @include hover {
1499
+ background-color: transparent;
1500
+ color: var(--o-color-primary1);
1501
+ }
1502
+ }
1503
+
1504
+ .o-btn.o-btn-text {
1505
+ padding-left: 0 !important;
1506
+ padding-right: 0 !important;
1507
+ min-width: auto;
1508
+ }
1509
+ }
1510
+
1511
+ .load-text {
1512
+ text-align: center;
1513
+ color: var(--o-color-info3);
1514
+ @include tip1;
1515
+ }
1516
+ }
1517
+ }
1518
+
1519
+ </style>
1520
+
1521
+ <style lang="scss">
1522
+ .handle-dialog-active {
1523
+ --activity-card-radius: var(--o-radius-xs);
1524
+ width: 450px;
1525
+ --dlg-radius: var(--activity-card-radius);
1526
+
1527
+ .o-dlg-header {
1528
+ margin-bottom: var(--o-gap-5);
1529
+ }
1530
+
1531
+ .o-dlg-body-content {
1532
+ display: flex;
1533
+ justify-content: center;
1534
+ }
1535
+
1536
+ .dialog-content {
1537
+ margin-bottom: var(--o-gap-2);
1538
+ }
1539
+ }
1540
+ </style>