mirror of
https://gitee.com/ccnetcore/Yi
synced 2026-04-11 11:46:38 +08:00
599 lines
13 KiB
Vue
599 lines
13 KiB
Vue
|
|
<script lang="ts" setup>
|
|||
|
|
import { storeToRefs } from 'pinia'
|
|||
|
|
import { ElMessage } from 'element-plus'
|
|||
|
|
import { useRouter } from 'vue-router'
|
|||
|
|
import type { Activity, Announcement } from '@/api'
|
|||
|
|
import { useAnnouncementStore } from '@/stores'
|
|||
|
|
import type { CloseType } from '@/stores/modules/announcement'
|
|||
|
|
|
|||
|
|
const router = useRouter()
|
|||
|
|
const announcementStore = useAnnouncementStore()
|
|||
|
|
|
|||
|
|
const activeTab = ref('activity')
|
|||
|
|
|
|||
|
|
// 窗口宽度响应式状态
|
|||
|
|
const windowWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1920)
|
|||
|
|
|
|||
|
|
// 监听窗口大小变化
|
|||
|
|
onMounted(() => {
|
|||
|
|
const handleResize = () => {
|
|||
|
|
windowWidth.value = window.innerWidth
|
|||
|
|
}
|
|||
|
|
window.addEventListener('resize', handleResize)
|
|||
|
|
onUnmounted(() => {
|
|||
|
|
window.removeEventListener('resize', handleResize)
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 响应式弹窗宽度
|
|||
|
|
const dialogWidth = computed(() => {
|
|||
|
|
if (windowWidth.value < 768) return '95%'
|
|||
|
|
if (windowWidth.value < 1024) return '90%'
|
|||
|
|
return '700px'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 从store获取数据
|
|||
|
|
const { carousels, activities, announcements, isDialogVisible } = storeToRefs(announcementStore)
|
|||
|
|
|
|||
|
|
// 分离最新公告和历史公告
|
|||
|
|
const latestAnnouncements = computed(() =>
|
|||
|
|
announcements.value.filter(a => a.type === 'latest'),
|
|||
|
|
)
|
|||
|
|
const historyAnnouncements = computed(() =>
|
|||
|
|
announcements.value.filter(a => a.type === 'history'),
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// 处理关闭弹窗
|
|||
|
|
function handleClose(type: CloseType) {
|
|||
|
|
announcementStore.closeDialog(type)
|
|||
|
|
|
|||
|
|
const messages = {
|
|||
|
|
today: '今日内不再显示',
|
|||
|
|
week: '本周内不再显示',
|
|||
|
|
permanent: '公告已关闭',
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ElMessage.success(messages[type])
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查看活动详情
|
|||
|
|
function viewActivityDetail(activity: Activity) {
|
|||
|
|
router.push({
|
|||
|
|
name: 'activityDetail',
|
|||
|
|
params: { id: activity.id },
|
|||
|
|
})
|
|||
|
|
announcementStore.isDialogVisible = false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查看公告详情
|
|||
|
|
function viewAnnouncementDetail(announcement: Announcement) {
|
|||
|
|
router.push({
|
|||
|
|
name: 'announcementDetail',
|
|||
|
|
params: { id: announcement.id },
|
|||
|
|
})
|
|||
|
|
announcementStore.isDialogVisible = false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 格式化时间
|
|||
|
|
function formatTime(time: string) {
|
|||
|
|
const date = new Date(time)
|
|||
|
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<el-dialog
|
|||
|
|
v-model="isDialogVisible"
|
|||
|
|
title="系统公告"
|
|||
|
|
:width="dialogWidth"
|
|||
|
|
:close-on-click-modal="false"
|
|||
|
|
class="announcement-dialog"
|
|||
|
|
>
|
|||
|
|
<div class="announcement-dialog-content">
|
|||
|
|
<el-tabs v-model="activeTab" class="announcement-tabs">
|
|||
|
|
<!-- 活动Tab -->
|
|||
|
|
<el-tab-pane label="活动" name="activity">
|
|||
|
|
<div class="tab-content-wrapper">
|
|||
|
|
<div class="activity-content">
|
|||
|
|
<!-- 轮播图 -->
|
|||
|
|
<el-carousel
|
|||
|
|
v-if="carousels.length > 0"
|
|||
|
|
height="250px"
|
|||
|
|
class="carousel-container"
|
|||
|
|
>
|
|||
|
|
<el-carousel-item v-for="item in carousels" :key="item.id">
|
|||
|
|
<img
|
|||
|
|
:src="item.imageUrl"
|
|||
|
|
:alt="item.title"
|
|||
|
|
class="carousel-image"
|
|||
|
|
>
|
|||
|
|
<div v-if="item.title" class="carousel-title">
|
|||
|
|
{{ item.title }}
|
|||
|
|
</div>
|
|||
|
|
</el-carousel-item>
|
|||
|
|
</el-carousel>
|
|||
|
|
|
|||
|
|
<!-- 活动列表 -->
|
|||
|
|
<div class="activity-list">
|
|||
|
|
<div
|
|||
|
|
v-for="activity in activities"
|
|||
|
|
:key="activity.id"
|
|||
|
|
class="activity-item"
|
|||
|
|
>
|
|||
|
|
<div class="activity-header">
|
|||
|
|
<h3 class="activity-title">{{ activity.title }}</h3>
|
|||
|
|
<el-tag
|
|||
|
|
v-if="activity.status === 'active'"
|
|||
|
|
type="success"
|
|||
|
|
size="small"
|
|||
|
|
>
|
|||
|
|
进行中
|
|||
|
|
</el-tag>
|
|||
|
|
<el-tag
|
|||
|
|
v-else-if="activity.status === 'expired'"
|
|||
|
|
type="info"
|
|||
|
|
size="small"
|
|||
|
|
>
|
|||
|
|
已结束
|
|||
|
|
</el-tag>
|
|||
|
|
</div>
|
|||
|
|
<p class="activity-description">{{ activity.description }}</p>
|
|||
|
|
<div class="activity-footer">
|
|||
|
|
<span class="activity-time">{{ formatTime(activity.createdAt) }}</span>
|
|||
|
|
<el-button
|
|||
|
|
type="primary"
|
|||
|
|
link
|
|||
|
|
@click="viewActivityDetail(activity)"
|
|||
|
|
>
|
|||
|
|
查看详情
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</el-tab-pane>
|
|||
|
|
|
|||
|
|
<!-- 公告Tab -->
|
|||
|
|
<el-tab-pane label="公告" name="announcement">
|
|||
|
|
<div class="tab-content-wrapper">
|
|||
|
|
<div class="announcement-content">
|
|||
|
|
<!-- 最新公告 -->
|
|||
|
|
<div v-if="latestAnnouncements.length > 0" class="latest-section">
|
|||
|
|
<h3 class="section-title">最新公告</h3>
|
|||
|
|
<div
|
|||
|
|
v-for="announcement in latestAnnouncements"
|
|||
|
|
:key="announcement.id"
|
|||
|
|
class="announcement-item latest"
|
|||
|
|
>
|
|||
|
|
<div class="announcement-header">
|
|||
|
|
<h4 class="announcement-title">
|
|||
|
|
<el-icon v-if="announcement.isImportant" color="#f56c6c">
|
|||
|
|
<i-ep-warning />
|
|||
|
|
</el-icon>
|
|||
|
|
{{ announcement.title }}
|
|||
|
|
</h4>
|
|||
|
|
<span class="announcement-time">{{ formatTime(announcement.publishTime) }}</span>
|
|||
|
|
</div>
|
|||
|
|
<p class="announcement-summary">{{ announcement.content.substring(0, 100) }}...</p>
|
|||
|
|
<el-button
|
|||
|
|
type="primary"
|
|||
|
|
link
|
|||
|
|
@click="viewAnnouncementDetail(announcement)"
|
|||
|
|
>
|
|||
|
|
查看详情
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 历史公告(时间线) -->
|
|||
|
|
<div v-if="historyAnnouncements.length > 0" class="history-section">
|
|||
|
|
<h3 class="section-title">历史公告</h3>
|
|||
|
|
<el-timeline>
|
|||
|
|
<el-timeline-item
|
|||
|
|
v-for="announcement in historyAnnouncements"
|
|||
|
|
:key="announcement.id"
|
|||
|
|
:timestamp="formatTime(announcement.publishTime)"
|
|||
|
|
placement="top"
|
|||
|
|
>
|
|||
|
|
<div class="timeline-item-content">
|
|||
|
|
<h4 class="timeline-title">{{ announcement.title }}</h4>
|
|||
|
|
<p class="timeline-summary">{{ announcement.content.substring(0, 80) }}...</p>
|
|||
|
|
<el-button
|
|||
|
|
type="primary"
|
|||
|
|
link
|
|||
|
|
size="small"
|
|||
|
|
@click="viewAnnouncementDetail(announcement)"
|
|||
|
|
>
|
|||
|
|
查看详情
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</el-timeline-item>
|
|||
|
|
</el-timeline>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</el-tab-pane>
|
|||
|
|
</el-tabs>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 底部按钮 -->
|
|||
|
|
<template #footer>
|
|||
|
|
<div class="dialog-footer">
|
|||
|
|
<el-button @click="handleClose('week')">本周关闭</el-button>
|
|||
|
|
<el-button @click="handleClose('today')">今日关闭</el-button>
|
|||
|
|
<el-button type="primary" @click="handleClose('permanent')">
|
|||
|
|
关闭公告
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
</el-dialog>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
// 确保弹窗本身不会溢出
|
|||
|
|
:deep(.el-dialog) {
|
|||
|
|
margin-top: 5vh !important;
|
|||
|
|
margin-bottom: 5vh !important;
|
|||
|
|
max-height: 90vh;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
:deep(.el-dialog__body) {
|
|||
|
|
overflow: hidden;
|
|||
|
|
flex: 1;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
padding: 0 !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-dialog-content {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
height: 100%;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-tabs {
|
|||
|
|
flex: 1;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
overflow: hidden;
|
|||
|
|
|
|||
|
|
:deep(.el-tabs__header) {
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
margin: 0 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
:deep(.el-tabs__content) {
|
|||
|
|
flex: 1;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
:deep(.el-tab-pane) {
|
|||
|
|
height: auto;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tab-content-wrapper {
|
|||
|
|
height: 60vh;
|
|||
|
|
max-height: 60vh;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
overflow-x: hidden;
|
|||
|
|
padding: 0 20px 20px;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
|
|||
|
|
// 确保滚动条样式
|
|||
|
|
&::-webkit-scrollbar {
|
|||
|
|
width: 6px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&::-webkit-scrollbar-track {
|
|||
|
|
background: #f1f1f1;
|
|||
|
|
border-radius: 3px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&::-webkit-scrollbar-thumb {
|
|||
|
|
background: #c1c1c1;
|
|||
|
|
border-radius: 3px;
|
|||
|
|
|
|||
|
|
&:hover {
|
|||
|
|
background: #a8a8a8;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-content {
|
|||
|
|
min-height: min-content;
|
|||
|
|
|
|||
|
|
.carousel-container {
|
|||
|
|
margin-bottom: 24px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.carousel-image {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
object-fit: cover;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.carousel-title {
|
|||
|
|
position: absolute;
|
|||
|
|
bottom: 0;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
padding: 12px 16px;
|
|||
|
|
background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
|
|||
|
|
color: #fff;
|
|||
|
|
font-size: 16px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-list {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-item {
|
|||
|
|
padding: 16px;
|
|||
|
|
background: #f5f7fa;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
transition: all 0.3s;
|
|||
|
|
|
|||
|
|
&:hover {
|
|||
|
|
background: #e8eaed;
|
|||
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-header {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 12px;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-title {
|
|||
|
|
margin: 0;
|
|||
|
|
font-size: 16px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #303133;
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-description {
|
|||
|
|
margin: 0 0 12px 0;
|
|||
|
|
color: #606266;
|
|||
|
|
font-size: 14px;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-footer {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-time {
|
|||
|
|
font-size: 12px;
|
|||
|
|
color: #909399;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-content {
|
|||
|
|
min-height: min-content;
|
|||
|
|
|
|||
|
|
.section-title {
|
|||
|
|
margin: 0 0 16px 0;
|
|||
|
|
font-size: 16px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #303133;
|
|||
|
|
padding-bottom: 8px;
|
|||
|
|
border-bottom: 2px solid #409eff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.latest-section {
|
|||
|
|
margin-bottom: 32px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-item {
|
|||
|
|
padding: 16px;
|
|||
|
|
background: #f5f7fa;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
transition: all 0.3s;
|
|||
|
|
|
|||
|
|
&:hover {
|
|||
|
|
background: #e8eaed;
|
|||
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&.latest {
|
|||
|
|
border-left: 3px solid #409eff;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-header {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-title {
|
|||
|
|
margin: 0;
|
|||
|
|
font-size: 15px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #303133;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 6px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-time {
|
|||
|
|
font-size: 12px;
|
|||
|
|
color: #909399;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-summary {
|
|||
|
|
margin: 0 0 12px 0;
|
|||
|
|
color: #606266;
|
|||
|
|
font-size: 14px;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.history-section {
|
|||
|
|
:deep(.el-timeline) {
|
|||
|
|
padding-left: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.timeline-item-content {
|
|||
|
|
padding-left: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.timeline-title {
|
|||
|
|
margin: 0 0 8px 0;
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #303133;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.timeline-summary {
|
|||
|
|
margin: 0 0 8px 0;
|
|||
|
|
color: #606266;
|
|||
|
|
font-size: 13px;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dialog-footer {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: flex-end;
|
|||
|
|
gap: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 移动端适配
|
|||
|
|
@media screen and (max-width: 768px) {
|
|||
|
|
:deep(.el-dialog) {
|
|||
|
|
margin: 5vh auto !important;
|
|||
|
|
max-height: 90vh;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
:deep(.el-dialog__header) {
|
|||
|
|
padding: 16px;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
:deep(.el-dialog__footer) {
|
|||
|
|
padding: 12px;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-tabs {
|
|||
|
|
:deep(.el-tabs__header) {
|
|||
|
|
margin: 0 12px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tab-content-wrapper {
|
|||
|
|
height: calc(90vh - 230px);
|
|||
|
|
max-height: calc(90vh - 230px);
|
|||
|
|
padding: 0 12px 12px;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
-webkit-overflow-scrolling: touch;
|
|||
|
|
|
|||
|
|
// 移动端滚动条样式
|
|||
|
|
&::-webkit-scrollbar {
|
|||
|
|
width: 4px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-content {
|
|||
|
|
.carousel-container {
|
|||
|
|
margin-bottom: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.carousel-title {
|
|||
|
|
padding: 8px 12px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-item {
|
|||
|
|
padding: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-description {
|
|||
|
|
font-size: 13px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.activity-footer {
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
gap: 8px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-content {
|
|||
|
|
.section-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-item {
|
|||
|
|
padding: 12px;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-summary {
|
|||
|
|
font-size: 13px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.history-section {
|
|||
|
|
.timeline-title {
|
|||
|
|
font-size: 13px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.timeline-summary {
|
|||
|
|
font-size: 12px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dialog-footer {
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 8px;
|
|||
|
|
|
|||
|
|
.el-button {
|
|||
|
|
width: 100%;
|
|||
|
|
margin: 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 平板适配 (768px - 1024px)
|
|||
|
|
@media screen and (min-width: 768px) and (max-width: 1024px) {
|
|||
|
|
:deep(.el-dialog) {
|
|||
|
|
margin: 5vh auto !important;
|
|||
|
|
max-height: 90vh;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.announcement-tabs {
|
|||
|
|
max-height: calc(90vh - 200px);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|