yunsan-pc/src/views/traffic/components/Traffic7.vue

227 lines
5.9 KiB
Vue

<template>
<section class="traffic-7">
<StationTimeFilter
class="traffic-7__filter"
v-model:line="selectedLine"
v-model:station="selectedStation"
v-model:month="selectedMonth"
/>
<div class="activity-list">
<article v-for="activity in activityList" :key="activity.id" class="activity-card">
<div class="activity-status" :class="`activity-status--${activity.statusType}`">
{{ activity.status }}
</div>
<h3 class="activity-name">{{ activity.name }}</h3>
<div class="activity-meta">
<span class="activity-label">时间:</span>
<span>{{ activity.time }}</span>
</div>
<div v-if="activity.venue" class="activity-meta activity-meta--venue">
<span class="activity-label">:</span>
<span>{{ activity.venue }}</span>
</div>
</article>
</div>
</section>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import dayjs from 'dayjs'
import StationTimeFilter from './StationTimeFilter.vue'
import server from '@/utils/service'
import { formatActivityMonth, processBigActivityList } from '@/utils/traffic'
const selectedLine = ref('7')
const selectedStation = ref('0753')
const selectedMonth = ref(dayjs().format('YYYY-M'))
const activityList = ref([])
const lineApiIdMap = ref({})
const loadLineApiIdMap = async () => {
try {
const response = await server.getLineList()
if (response.data.success && response.data.data?.length) {
lineApiIdMap.value = Object.fromEntries(
response.data.data.map(item => [String(item.lineId), String(item.id)])
)
}
} catch (error) {
console.error('获取线路列表失败:', error)
}
}
const fetchActivityList = async () => {
const metroLine = lineApiIdMap.value[selectedLine.value]
if (!metroLine || !selectedStation.value || !selectedMonth.value) {
activityList.value = []
return
}
try {
const response = await server.getBigActivityList({
metroLine,
metroStation: selectedStation.value,
activityMonth: formatActivityMonth(selectedMonth.value)
})
if (response.data.success) {
activityList.value = processBigActivityList(response.data.data)
} else {
activityList.value = []
}
} catch (error) {
console.error('获取重大活动清单失败:', error)
activityList.value = []
}
}
watch([selectedLine, selectedStation, selectedMonth], fetchActivityList)
onMounted(async () => {
await loadLineApiIdMap()
await fetchActivityList()
})
</script>
<style lang="scss" scoped>
.traffic-7 {
position: absolute;
left: 2948px;
top: 707px;
width: 892px;
height: 880px;
background: url('/imgs/traffic/7-bg.png') no-repeat center center;
background-size: cover;
.traffic-7__filter {
position: absolute;
top: 12px;
right: 30px;
z-index: 2;
}
.activity-list {
position: absolute;
top: 75px;
right: 12px;
bottom: 20px;
left: 20px;
display: flex;
flex-direction: column;
gap: 15px;
overflow-x: hidden;
overflow-y: scroll;
padding-right: 6px;
}
.activity-card {
position: relative;
min-height: 89px;
box-sizing: border-box;
padding: 12px 104px 10px 31px;
overflow: hidden;
border-radius: 5px;
letter-spacing: 0.03em;
flex-shrink: 0;
background: rgba(44, 121, 236, 0.35);
}
.activity-empty {
height: 100%;
:deep(.el-empty__description p) {
color: rgba(220, 236, 255, 0.78);
font-size: 18px;
font-weight: 700;
}
}
.activity-name {
margin: 0;
color: #FFFFFF;
font-size: 22px;
font-weight: 500;
line-height: 32px;
letter-spacing: 0.03em;
}
.activity-meta {
display: flex;
align-items: center;
// gap: 37px;
margin-top: 7px;
color: rgba(255, 255, 255, 0.8);
font-size: 20px;
font-weight: 400;
line-height: 28px;
white-space: nowrap;
&--venue {
margin-top: 7px;
}
}
.activity-label {
color: rgba(228, 243, 255, 0.74);
flex-shrink: 0;
width: 94px;
}
.activity-status {
position: absolute;
top: 0;
right: 0;
z-index: 1;
width: 91px;
height: 35px;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
font-weight: 500;
line-height: 1;
text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5);
&::before {
content: '';
position: absolute;
top: 0;
left: -20px;
width: 0;
height: 0;
border-top: 35px solid var(--status-bg-start);
border-left: 20px solid transparent;
}
&--active {
--status-bg-start: #078b66;
--status-bg-end: #08b279;
color: #02FF5F;
background: linear-gradient(90deg, var(--status-bg-start) 0%, var(--status-bg-end) 100%);
}
&--ended {
--status-bg-start: #9b7f7f;
--status-bg-end: #bba1a1;
color: #cfcfcf;
background: linear-gradient(90deg, var(--status-bg-start) 0%, var(--status-bg-end) 100%);
}
&--pending {
--status-bg-start: #546174;
--status-bg-end: #6f7c91;
color: #f0f0f0;
background: linear-gradient(90deg, var(--status-bg-start) 0%, var(--status-bg-end) 100%);
}
}
}
</style>