|
@@ -0,0 +1,547 @@
|
|
|
+<template>
|
|
|
+ <div class="visit8">
|
|
|
+ <div class="banner8">
|
|
|
+ <van-swipe :show-indicators="false" @change="(index) => currentBanner = index">
|
|
|
+ <van-swipe-item v-for="item in bannerList" :key="`${item.id}-${selectedDay.getTime()}`">
|
|
|
+ <van-image
|
|
|
+ width="100%"
|
|
|
+ height="211px"
|
|
|
+ :src="item.cover"
|
|
|
+ style="cursor: pointer;"
|
|
|
+ @click="handleClick(item)"
|
|
|
+ />
|
|
|
+ </van-swipe-item>
|
|
|
+ </van-swipe>
|
|
|
+
|
|
|
+ <div class="banner8__footer">
|
|
|
+ <div><p class="limit-line">{{bannerList[currentBanner].h3}}</p><span>{{getBannerTag(bannerList[currentBanner]._type)}}</span></div>
|
|
|
+ <p>{{bannerList[currentBanner].i || bannerList[currentBanner].info.time}}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="choose-date">
|
|
|
+ <div :class="['choose-date__input', !startDate && 'placeholder']"
|
|
|
+ @click="showStartDatePicker = true"
|
|
|
+ >{{startDateLabel}}</div>
|
|
|
+ <div :class="['choose-date__input', !endDate && 'placeholder']"
|
|
|
+ @click="showEndDatePicker = true"
|
|
|
+ >{{endDateLabel}}</div>
|
|
|
+ <div class="choose-date__icon">
|
|
|
+ <img src="@/assets/img/Visit/icon_calender_active.png" @click="showDate = !showDate" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <Calendar v-show="showDate" v-model="selectedDay">
|
|
|
+ <template
|
|
|
+ slot="dateCell"
|
|
|
+ slot-scope="{date, data}">
|
|
|
+ {{ data.day.split('-')[2] }}
|
|
|
+ <div class="dots">
|
|
|
+ <!-- <div class="dot" /> -->
|
|
|
+ <div v-if="showDotEvent(data.day)" class="dot events" />
|
|
|
+ <div v-if="showDotLearn(data.day)" class="dot learn" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </Calendar>
|
|
|
+
|
|
|
+ <div class="type-container">
|
|
|
+ <div>
|
|
|
+ <div v-for="item in TYPE_LIST" :key="item.value"
|
|
|
+ :class="[currentType === item.value && 'active']"
|
|
|
+ @click="currentType = item.value"
|
|
|
+ >{{item.label}}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="main__list">
|
|
|
+ <div v-for="item in allList.slice((pageNum - 1) * pageSize, pageNum * pageSize)" :key="item.id" class="visit8-card" @click="handleClick(item)">
|
|
|
+ <div class="visit8-card__top">
|
|
|
+ <span v-for="txt in getEnDate(formatDate(new Date(Array.isArray(item.date) ? item.date[0] : item.date)))" :key="txt">{{ txt }}</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <van-image class="visit8-card__right" :src="item.cover" height="177px" />
|
|
|
+
|
|
|
+ <div class="visit8-card__main">
|
|
|
+ <p class="limit-line line-2">{{item.h3}}</p>
|
|
|
+
|
|
|
+ <div class="visit8-card__main__inner">
|
|
|
+ <p v-if="item.info">·{{item.info.time}}</p>
|
|
|
+ <p v-if="item.info">·{{item.info.loc}}</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="visit8-card__main__bt">
|
|
|
+ <span v-if="item.tag" class="visit8-card__tag">{{item.tag}}</span>
|
|
|
+ <img src="@/assets/img/Visit/icon_enter_normal.png" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="allList.length > 0" style="text-align: center;">
|
|
|
+ <Pagination
|
|
|
+ background
|
|
|
+ layout="prev, pager, next"
|
|
|
+ :total="allList.length"
|
|
|
+ :page-size="pageSize"
|
|
|
+ :pager-count="5"
|
|
|
+ @current-change="num => pageNum = num"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-else class="empty">no more</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <van-calendar v-model="showStartDatePicker" :min-date="minDate" @confirm="handleStartDateConfirm" />
|
|
|
+ <van-calendar v-model="showEndDatePicker" :min-date="startDate" @confirm="handleEndDateConfirm" />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ import { LearnEngage } from '../Learn/data';
|
|
|
+ import { AboutOne } from '../bottom/Events/data';
|
|
|
+ import { Pagination } from 'element-ui';
|
|
|
+ import Calendar from './components/calendar.vue';
|
|
|
+
|
|
|
+ const TYPE_LIST = [
|
|
|
+ { label: 'All', value: 0 },
|
|
|
+ { label: 'Exhibitions', value: 1 },
|
|
|
+ { label: 'Events', value: 2 },
|
|
|
+ { label: 'Learn & Engage', value: 3 },
|
|
|
+ ]
|
|
|
+
|
|
|
+ export default {
|
|
|
+ components: {
|
|
|
+ Calendar,
|
|
|
+ Pagination
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ TYPE_LIST,
|
|
|
+ currentBanner: 0,
|
|
|
+ currentType: TYPE_LIST[0].value,
|
|
|
+ selectedDay: new Date(),
|
|
|
+ startDate: new Date(),
|
|
|
+ endDate: null,
|
|
|
+ showDate: false,
|
|
|
+
|
|
|
+ showStartDatePicker: false,
|
|
|
+ showEndDatePicker: false,
|
|
|
+ minDate: new Date(2005, 0, 1),
|
|
|
+
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 3,
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ startDateLabel() {
|
|
|
+ if (!this.startDate) return 'Start Date';
|
|
|
+ return this.formatDate(this.startDate, true)
|
|
|
+ },
|
|
|
+ endDateLabel() {
|
|
|
+ if (!this.endDate) return 'End Date';
|
|
|
+ return this.formatDate(this.endDate, true)
|
|
|
+ },
|
|
|
+ allList() {
|
|
|
+ let temp = [];
|
|
|
+ let all = this.sortList;
|
|
|
+
|
|
|
+ if (this.startDate) {
|
|
|
+ const currentDate = this.getTimestamp(this.formatDate(this.startDate));
|
|
|
+ const endDate = this.getTimestamp(this.formatDate(this.endDate || new Date()));
|
|
|
+ all = this.sortList.filter(i => {
|
|
|
+ if (Array.isArray(i.date)) {
|
|
|
+ return (i.date[0] <= currentDate && i.date[1] >= currentDate) || (i.date[0] >= currentDate && !this.endDate);
|
|
|
+ }
|
|
|
+ return i.date >= currentDate && (this.endDate ? i.date <= endDate : true)
|
|
|
+ })
|
|
|
+ } else if (this.endDate) {
|
|
|
+ const endDate = this.getTimestamp(this.formatDate(this.endDate || new Date()));
|
|
|
+ all = this.sortList.filter(i => {
|
|
|
+ if (Array.isArray(i.date)) {
|
|
|
+ return i.date[0] <= endDate;
|
|
|
+ }
|
|
|
+ return i.date <= endDate
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (this.currentType) {
|
|
|
+ case 0:
|
|
|
+ temp = all;
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ temp = [];
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ temp = all.filter(i => i._type === 2);
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ temp = all.filter(i => i._type === 3);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return temp;
|
|
|
+ },
|
|
|
+ learnList() {
|
|
|
+ return [...LearnEngage.Students.map(i => ({
|
|
|
+ ...i,
|
|
|
+ date: !Array.isArray(i.info.date) ? this.getTimestamp(i.info.date) : [this.getTimestamp(i.info.date[0]), this.getTimestamp(i.info.date[1])],
|
|
|
+ tag: 'For Students',
|
|
|
+ cover: `/data/LearnEngage/sm/${i.id}.png`,
|
|
|
+ topId: 'Students',
|
|
|
+ _type: 3
|
|
|
+ })), ...LearnEngage.Adults.map(i => ({
|
|
|
+ ...i,
|
|
|
+ date: !Array.isArray(i.info.date) ? this.getTimestamp(i.info.date) : [this.getTimestamp(i.info.date[0]), this.getTimestamp(i.info.date[1])],
|
|
|
+ tag: 'For Adults',
|
|
|
+ topId: 'Adults',
|
|
|
+ cover: `/data/LearnEngage/sm/${i.id}.png`,
|
|
|
+ _type: 3
|
|
|
+ })), ...LearnEngage.Families.map(i => ({
|
|
|
+ ...i,
|
|
|
+ date: !Array.isArray(i.info.date) ? this.getTimestamp(i.info.date) : [this.getTimestamp(i.info.date[0]), this.getTimestamp(i.info.date[1])],
|
|
|
+ tag: 'For Families & Children',
|
|
|
+ topId: 'Families',
|
|
|
+ cover: `/data/LearnEngage/sm/${i.id}.png`,
|
|
|
+ _type: 3
|
|
|
+ }))]
|
|
|
+ },
|
|
|
+ exhibitionList() {
|
|
|
+ return [];
|
|
|
+ // 展览目前都与星期关联,不做展示
|
|
|
+ // return [...dataAll.Exhibitions.Current.map(i => ({
|
|
|
+ // ...i,
|
|
|
+ // tag: 'Current Exhibitions'
|
|
|
+ // })), ...dataAll.Exhibitions.Permanent.map(i => ({
|
|
|
+ // ...i,
|
|
|
+ // tag: 'Permanent Exhibitions'
|
|
|
+ // })), ...dataAll.Exhibitions.Overseas.map(i => ({
|
|
|
+ // ...i,
|
|
|
+ // tag: 'Overseas Exhibitions'
|
|
|
+ // }))]
|
|
|
+ },
|
|
|
+ eventList() {
|
|
|
+ return AboutOne.map(i => {
|
|
|
+ const { date, ...rest } = i
|
|
|
+ return {
|
|
|
+ ...rest,
|
|
|
+ _type: 2,
|
|
|
+ date: typeof date === 'string' ? this.getTimestamp(date) : [this.getTimestamp(date[0]), this.getTimestamp(date[1])]
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ sortList() {
|
|
|
+ const stack = [...this.learnList, ...this.eventList];
|
|
|
+ const currentDate = this.getTimestamp(this.formatDate(this.selectedDay));
|
|
|
+
|
|
|
+ stack.sort((a, b) => {
|
|
|
+ function getEndDate(date) {
|
|
|
+ if (Array.isArray(date)) {
|
|
|
+ return date[1];
|
|
|
+ }
|
|
|
+ return date;
|
|
|
+ }
|
|
|
+
|
|
|
+ const endDateA = getEndDate(a.date);
|
|
|
+ const endDateB = getEndDate(b.date);
|
|
|
+
|
|
|
+ if (endDateA >= currentDate && endDateB >= currentDate) {
|
|
|
+ // 如果两者都是进行中,则按照结束时间早的排在前面
|
|
|
+ return endDateA - endDateB;
|
|
|
+ } else if (endDateA >= currentDate) {
|
|
|
+ // 如果A进行中,B已结束,则A排在前面
|
|
|
+ return -1;
|
|
|
+ } else if (endDateB >= currentDate) {
|
|
|
+ // 如果B进行中,A已结束,则B排在前面
|
|
|
+ return 1;
|
|
|
+ } else {
|
|
|
+ // 如果两者都已结束,则按照结束时间晚的排在前面
|
|
|
+ return endDateB - endDateA;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return stack;
|
|
|
+ },
|
|
|
+ bannerList() {
|
|
|
+ return this.sortList.slice(0, 5);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ selectedDay(v) {
|
|
|
+ if (this.$refs.carousel) {
|
|
|
+ this.$refs.carousel.setActiveItem(0);
|
|
|
+ this.currentBanner = 0;
|
|
|
+ this.startDate = v;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ startDate(v) {
|
|
|
+ if (!v || (this.endDate && v.getTime() > this.endDate.getTime())) {
|
|
|
+ this.endDate = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ handleStartDateConfirm(date) {
|
|
|
+ this.startDate = date;
|
|
|
+ this.showStartDatePicker = false;
|
|
|
+ },
|
|
|
+ handleEndDateConfirm(date) {
|
|
|
+ this.endDate = date;
|
|
|
+ this.showEndDatePicker = false;
|
|
|
+ },
|
|
|
+ handleClick(item) {
|
|
|
+ switch (item._type) {
|
|
|
+ case 2:
|
|
|
+ this.$router.push(`/Layout/EventsInfo/${item.id}`);
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ this.$router.push({
|
|
|
+ name: "LearnEngageInfo",
|
|
|
+ query: { id: item.id, k: item.topId, m: this.pageSize },
|
|
|
+ });
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 切换页码
|
|
|
+ pageChange(val) {
|
|
|
+ this.pageSize = val;
|
|
|
+ window.scrollTo({ top: 900, behavior: "smooth" });
|
|
|
+ },
|
|
|
+ getBannerTag(type) {
|
|
|
+ switch (type) {
|
|
|
+ case 1:
|
|
|
+ return 'Exhibitions';
|
|
|
+ case 2:
|
|
|
+ return 'Events';
|
|
|
+ case 3:
|
|
|
+ return 'Learn & Engage';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleType(type) {
|
|
|
+ this.currentType = type;
|
|
|
+ },
|
|
|
+ formatDate(date, isLabel) {
|
|
|
+ const year = date.getFullYear();
|
|
|
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
|
+ const day = date.getDate().toString().padStart(2, '0');
|
|
|
+ return isLabel ? month + '/' + day + '/' + year : year + '-' + month + '-' + day;
|
|
|
+ },
|
|
|
+ getTimestamp(date) {
|
|
|
+ return new Date(date + ' 00:00:00').getTime();
|
|
|
+ },
|
|
|
+ showDotEvent(date) {
|
|
|
+ const timestamp = new Date(date + ' 00:00:00').getTime();
|
|
|
+ return this.eventList.some(i => {
|
|
|
+ if (typeof i.date === 'number') return i.date === timestamp;
|
|
|
+ return i.date[0] <= timestamp && timestamp <= i.date[1];
|
|
|
+ })
|
|
|
+ },
|
|
|
+ showDotLearn(date) {
|
|
|
+ const timestamp = new Date(date + ' 00:00:00').getTime();
|
|
|
+ return this.learnList.some(i => {
|
|
|
+ if (typeof i.date === 'number') return (i.date) === timestamp;
|
|
|
+ return i.date[0] <= timestamp && timestamp <= i.date[1];
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleBanner(idx) {
|
|
|
+ this.currentBanner = idx;
|
|
|
+ },
|
|
|
+ getEnDate(d) {
|
|
|
+ const date = new Date(d);
|
|
|
+ const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
|
+ const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
|
+
|
|
|
+ const month = months[date.getMonth()];
|
|
|
+ const day = date.getDate();
|
|
|
+ const dayOfWeek = daysOfWeek[date.getDay()];
|
|
|
+
|
|
|
+ return [`${dayOfWeek} , `, month, day];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less" scoped>
|
|
|
+.dots {
|
|
|
+ display: flex;
|
|
|
+ gap: 5px;
|
|
|
+ margin-top: 3px;
|
|
|
+ height: 5px;
|
|
|
+
|
|
|
+ .dot {
|
|
|
+ width: 5px;
|
|
|
+ height: 5px;
|
|
|
+ border-radius: 5px;
|
|
|
+ background-color: #BC1C24;
|
|
|
+
|
|
|
+ &.events {
|
|
|
+ background-color: #D2B986;
|
|
|
+ }
|
|
|
+ &.learn {
|
|
|
+ background-color: #95D2FF;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.type-container {
|
|
|
+ padding: 0 11px;
|
|
|
+ margin: 20px 0 5px;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ div {
|
|
|
+ display: flex;
|
|
|
+ gap: 5px;
|
|
|
+ height: 44px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+
|
|
|
+ div {
|
|
|
+ padding: 0 16px;
|
|
|
+ height: 42px;
|
|
|
+ line-height: 42px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #202020;
|
|
|
+ white-space: nowrap;
|
|
|
+ background: rgba(255,255,255,0.2);
|
|
|
+ border: 1px solid #D2B986;
|
|
|
+ border-radius: 5px;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ border: none;
|
|
|
+ color: white;
|
|
|
+ background-color: #BC1C24;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+.empty {
|
|
|
+ text-align: center;
|
|
|
+ font-size: 16px;
|
|
|
+ padding: 20px 0;
|
|
|
+ color: #666666;
|
|
|
+}
|
|
|
+::v-deep .el-pagination.is-background .el-pager li:not(.disabled).active {
|
|
|
+ background-color: #BC1C24;
|
|
|
+}
|
|
|
+.banner8 {
|
|
|
+ &__footer {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 7px 15px 10px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #000;
|
|
|
+ background-color: white;
|
|
|
+
|
|
|
+ div:first-child {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 16px;
|
|
|
+
|
|
|
+ p {
|
|
|
+ flex: 1;
|
|
|
+ width: 0;
|
|
|
+ line-height: 24px;
|
|
|
+ }
|
|
|
+ span {
|
|
|
+ margin-left: 16px;
|
|
|
+ padding: 5px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #D2B986;
|
|
|
+ background: rgba(210,185,134,0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ white-space: nowrap;
|
|
|
+ border: 1px solid #D2B986;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.main__list {
|
|
|
+ padding: 0 20px;
|
|
|
+}
|
|
|
+.visit8-card {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ background-color: white;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ padding: 10px 15px 25px;
|
|
|
+ box-shadow: 0px 3px 6px rgba(68,58,54,0.16);
|
|
|
+
|
|
|
+ &__top {
|
|
|
+ margin-bottom: 10px;
|
|
|
+ color: #D2B986;
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ &__main {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+
|
|
|
+ > p {
|
|
|
+ margin: 10px 0;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 16px;
|
|
|
+ line-height: 18px;
|
|
|
+ }
|
|
|
+ &__inner {
|
|
|
+ color: #6A6A6A;
|
|
|
+ font-size: 14px;
|
|
|
+
|
|
|
+ p {
|
|
|
+ line-height: 18px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &__bt {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-end;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-top: 15px;
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 33px;
|
|
|
+ height: 33px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &__tag {
|
|
|
+ height: 30px;
|
|
|
+ line-height: 30px;
|
|
|
+ padding: 0 10px;
|
|
|
+ color: #D2B986;
|
|
|
+ font-size: 12px;
|
|
|
+ background: rgba(210,185,134,0.12);
|
|
|
+ border: 1px solid #D2B986;
|
|
|
+ border-radius: 5px;
|
|
|
+ }
|
|
|
+}
|
|
|
+.choose-date {
|
|
|
+ display: flex;
|
|
|
+ gap: 5px;
|
|
|
+ padding: 18px 10px 0;
|
|
|
+
|
|
|
+ &__input {
|
|
|
+ flex: 1;
|
|
|
+ padding: 0 14px;
|
|
|
+ height: 44px;
|
|
|
+ line-height: 42px;
|
|
|
+ background: rgba(255,255,255,0.2);
|
|
|
+ border: 1px solid #D2B986;
|
|
|
+ border-radius: 5px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #202020;
|
|
|
+
|
|
|
+ &.placeholder {
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &__icon {
|
|
|
+ flex: 0 0 44px;
|
|
|
+ height: 44px;
|
|
|
+ background: #D2B986;
|
|
|
+ border-radius: 5px;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 44px;
|
|
|
+ height: 44px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|