You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CaiYuanYiTiHua/src/views/subject/index.vue

507 lines
13 KiB
Vue

<template>
<div class="subject">
<div class="subject_header">
<img class="subject_header_img" src="/subject/subject_header.png" />
<div class="subject_header_title">
<span>
<img src="/subject/subject_logo.png" />
{{ t('sys.subject.header_title') }}
</span>
</div>
<div class="subject_header_adminAndLogout">
<img src="/subject/subject_header_admin.png" />
<span> {{ loginUser }} {{ t('sys.subject.header_admin') }}</span>
&nbsp;&nbsp;&nbsp;&nbsp;
<img src="/subject/subject_header_logout.png" @click="handleLoginOut()" />
<span @click="handleLoginOut()">{{ t('sys.subject.header_logout') }}</span>
</div>
</div>
<div class="subject_box">
<div class="subject_box_btn" ref="contentArea">
<div
v-for="(item, index) in list"
:key="item.id"
:id="item.id"
class="subject_box_btn_div"
@click="getHome(item)"
:style="{
'background-image': `url(${index % 2 == 0 ? '/subject/subject_btn_1.png' : '/subject/subject_btn_2.png'})`,
'background-size': 'cover',
'background-repeat': 'no-repeat',
}"
>
<img class="subject_box_btn_div_url" :src="getImageUrl(item.imgUrl)" />
<span
class="subject_box_btn_div_span"
:style="{ height: `${28 * spanWrap + 8}px` }"
v-html="renderedTitle(item.title)"
/>
<img
class="subject_box_btn_div_line"
src="/subject/subject_line.png"
:style="{
top: `${14 * getWrap(item.title) - 14 * (spanWrap - 1) - 8}px`,
}"
/>
<div class="circle arc1" :style="{ top: `${-126 * 1 - 28 * spanWrap}px` }" />
<div class="circle arc2" :style="{ top: `${-126 * 2 - 28 * spanWrap}px` }" />
<div class="circle arc3" :style="{ top: `${-126 * 3 - 28 * spanWrap}px` }" />
<div class="circle arc4" :style="{ top: `${-126 * 4 - 28 * spanWrap}px` }" />
</div>
</div>
<div class="subject_box_overflow">
<Icon
v-if="list.length > 14"
style="font-size: 31px"
class="subject_box_overflow_icon1"
icon="ant-design:up-outlined"
@click="scrollToElement('top')"
/>
<Icon
v-if="list.length > 14"
style="font-size: 31px"
class="subject_box_overflow_icon2"
icon="ant-design:down-outlined"
@click="scrollToElement('bottom')"
/>
</div>
</div>
<div class="subject_bottom">
<span>
{{ t('sys.subject.bottom_copyright') }}
&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;
{{ t('sys.subject.bottom_support') }}
&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;
{{ t('sys.subject.bottom_version') }}
</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useUserStore } from '@/store/modules/user';
import { getSpecialData } from '@/api/demo/system';
import { onMounted, ref, nextTick } from 'vue';
import { message } from 'ant-design-vue';
import Icon from '@/components/Icon/Icon.vue';
import { getAppEnvConfig } from '@/utils/env';
import { useI18n } from '@/hooks/web/useI18n';
import { PageEnum } from '@/enums/pageEnum';
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const VITE_GLOB_API_URL_VAR = ref<String>(VITE_GLOB_API_URL + '/');
const { t } = useI18n();
const loginUser: any = ref('');
const contentArea = ref<HTMLElement | null>(null);
const list: any = ref([]);
const userStore = useUserStore();
const spanWrap = ref(1);
async function getData() {
const res: any = await getSpecialData();
// 最大标题文字行数
res?.forEach((item) => {
if (Math.ceil(item.title.length / 6) > spanWrap.value) {
spanWrap.value = Math.ceil(item.title.length / 6);
}
});
list.value = res;
loginUser.value = localStorage.getItem('fireUserLoginName');
// cardRotationLoop();
}
// 旋转动画
async function cardRotationLoop() {
nextTick(() => {
list.value.forEach((item, index) => {
setTimeout(() => {
const element: any = document.getElementById(item.id);
element.classList.remove('cardRotationState');
element.classList.add('cardRotation');
setTimeout(() => {
element.classList.add('cardRotationState');
}, 5000);
if (index == list.value.length - 1) {
setTimeout(() => {
cardRotationLoop();
}, 8000);
}
}, index * 8000);
});
});
}
// 按键控制滚动条
const scrollToElement = async (type) => {
if (contentArea.value) {
if (type == 'top' && contentArea.value.scrollTop != 0) {
contentArea.value.scrollTop = contentArea.value.scrollTop - 344;
}
if (type == 'bottom' && contentArea.value.scrollTop != contentArea.value.scrollHeight) {
contentArea.value.scrollTop = contentArea.value.scrollTop + 344;
}
}
};
// 跳转
async function getHome(item) {
console.log(window.innerWidth);
if (!item.isDevelop) {
message.warn(item.title + '系统暂未开放!');
return;
}
if (item.isExternal) {
if (item.linkOrApi) {
window.location.href = item.linkOrApi;
} else {
message.warn('系统外部链接未配置!');
return;
}
} else {
if (!item.linkOrApi) {
item.linkOrApi = PageEnum.WELCOME_HOME;
}
userStore.setSubject(item.id, item.logoTitle, item.linkOrApi);
}
}
// 获取图片地址
function getImageUrl(imgUrl) {
if (imgUrl) {
return VITE_GLOB_API_URL_VAR.value + imgUrl;
} else {
return '/subject/subject_default.png';
}
}
// 标题换行
function renderedTitle(name) {
return `${name.replace(/\s/g, '<br />')}`;
}
// 标题的行数
function getWrap(name) {
return Math.ceil(name.length / 6);
}
// 退出系统
function handleLoginOut() {
userStore.confirmLoginOut();
}
onMounted(() => {
getData();
});
</script>
<style lang="less" scoped>
.subject {
background-image: url('/subject/subject_bg.png');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
background-attachment: fixed;
width: 100%;
height: 100%;
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
user-select: none;
&_header {
&_img {
height: 82px;
width: 100%;
}
&_title {
position: relative;
top: -87px;
span {
img {
position: relative;
top: 3px;
width: 78px;
height: 71px;
margin-right: 10px;
}
display: inline-flex;
align-items: center;
text-align: center;
justify-content: center;
width: 100%;
height: 82px;
font-family: 068-SSZhengYaTi;
font-weight: 400;
font-size: 42px;
color: #ffffff;
font-weight: 900 !important;
letter-spacing: 2px;
}
}
&_adminAndLogout {
position: absolute;
right: 87px;
top: 0px;
height: 40px;
display: inline-flex;
align-items: center;
img {
cursor: pointer;
width: 31px;
height: 31px;
}
span {
cursor: pointer;
display: inline-flex;
align-items: center;
text-align: center;
justify-content: center;
height: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 14px;
color: #006cff;
line-height: 28px;
}
}
}
&_box {
display: flex;
position: relative;
top: -82px;
&_btn {
align-items: center;
display: flex;
flex-wrap: wrap;
position: relative;
top: 50px;
left: 100px;
height: 688px;
width: calc(100vw);
display: flex;
overflow-x: hidden;
overflow-y: auto;
-ms-overflow-style: none; /* IE 和 Edge */
scrollbar-width: none; /* Firefox */
::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera */
}
&_div {
flex: 0 0 auto;
margin-right: 20px;
margin-bottom: 20px;
width: 225px;
height: 325px;
transition: all 0.3s ease;
padding: 10px;
// 定义旋转
// 设置透视距离
perspective: 1000px;
// 添加过渡效果
transition: transform 1s;
// 定义旋转动画
// animation: cardRotation 5s linear infinite;
&:hover {
filter: brightness(150%);
cursor: pointer;
box-shadow: 20px 10px 10px rgba(0, 0, 0, 0.5);
// 定义旋转
// 暂停动画
animation-play-state: paused;
// 过渡效果
transition: transform 1s ease;
// 立即回到正面
transform: rotateY(0deg) !important;
}
&_bg {
height: 324px;
}
&_url {
position: relative;
top: 0px;
left: 11px;
width: 191px;
height: 191px;
}
&_span {
display: inline-flex;
align-items: center;
text-align: center;
justify-content: center;
position: relative;
// top: -300px;
left: 12px;
width: 190px;
// 字体样式
font-size: 28px;
font-family: 'Microsoft YaHei';
color: #ffffff;
background: linear-gradient(0deg, #6da7ff 0%, #e2ebff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
color: transparent;
font-weight: 900 !important;
}
&_line {
position: relative;
left: 42px;
width: 128px;
height: 7px;
}
}
}
&_overflow {
position: absolute;
top: 220px;
right: -110px;
height: 300px;
width: 110px;
&_icon1 {
color: #006cff;
cursor: pointer;
position: relative;
top: 100px;
right: 85px;
}
&_icon2 {
color: #006cff;
cursor: pointer;
position: relative;
top: 200px;
right: 115px;
}
}
}
&_bottom {
span {
width: 902px;
height: 18px;
font-family: PingFang SC;
font-weight: 400;
font-size: 18px;
color: #5eb2ff;
}
position: absolute;
top: 95%;
left: calc(50% - 902px / 2);
}
}
// 四条旋转的弧线
.circle {
transform-origin: 50% 50%;
width: 126px;
height: 126px;
border-radius: 50%;
background-color: transparent;
border: 3px solid #276fff;
}
.arc1 {
position: relative;
// top: -142px;
left: 108px;
clip-path: inset(0 55% 55% 0);
animation: rotateArc1 8s linear infinite;
}
.arc2 {
position: relative;
top: -268px;
left: 108px;
clip-path: inset(55% 0 0 55%);
transform: rotate(90deg);
animation: rotateArc2 8s linear infinite;
}
.arc3 {
position: relative;
top: -394px;
left: 108px;
clip-path: inset(0 55% 55% 0);
transform: rotate(180deg);
animation: rotateArc3 8s linear infinite;
}
.arc4 {
position: relative;
top: -520px;
left: 108px;
clip-path: inset(55% 0 0 55%);
transform: rotate(270deg);
animation: rotateArc4 8s linear infinite;
}
@keyframes rotateArc1 {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
transform: translate(-50%, -50%) rotate(360deg);
}
}
@keyframes rotateArc2 {
0% {
transform: translate(-50%, -50%) rotate(90deg);
}
100% {
transform: translate(-50%, -50%) rotate(450deg);
}
}
@keyframes rotateArc3 {
0% {
transform: translate(-50%, -50%) rotate(180deg);
}
100% {
transform: translate(-50%, -50%) rotate(540deg);
}
}
@keyframes rotateArc4 {
0% {
transform: translate(-50%, -50%) rotate(270deg);
}
100% {
transform: translate(-50%, -50%) rotate(630deg);
}
}
// 开启旋转动画
.cardRotation {
animation: cardRotation 5s linear infinite;
}
// 关闭旋转动画
.cardRotationState {
animation-play-state: paused;
transition: transform 3s ease;
transform: rotateY(0deg) !important;
}
// 定义旋转动画
@keyframes cardRotation {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(-360deg);
}
}
</style>