@@ -11,6 +11,7 @@ | |||
"echarts": "^5.4.3", | |||
"element-plus": "^2.4.4", | |||
"pinia": "^2.1.7", | |||
"screenfull": "^6.0.2", | |||
"vue": "^3.3.11", | |||
"vue3-marquee": "^4.1.0" | |||
}, | |||
@@ -1123,6 +1124,14 @@ | |||
"fsevents": "~2.3.2" | |||
} | |||
}, | |||
"node_modules/screenfull": { | |||
"version": "6.0.2", | |||
"resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-6.0.2.tgz", | |||
"integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==", | |||
"engines": { | |||
"node": "^14.13.1 || >=16.0.0" | |||
} | |||
}, | |||
"node_modules/source-map-js": { | |||
"version": "1.0.2", | |||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", | |||
@@ -1888,6 +1897,11 @@ | |||
"fsevents": "~2.3.2" | |||
} | |||
}, | |||
"screenfull": { | |||
"version": "6.0.2", | |||
"resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-6.0.2.tgz", | |||
"integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==" | |||
}, | |||
"source-map-js": { | |||
"version": "1.0.2", | |||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", | |||
@@ -12,6 +12,7 @@ | |||
"echarts": "^5.4.3", | |||
"element-plus": "^2.4.4", | |||
"pinia": "^2.1.7", | |||
"screenfull": "^6.0.2", | |||
"vue": "^3.3.11", | |||
"vue3-marquee": "^4.1.0" | |||
}, | |||
@@ -26,7 +26,7 @@ watch(() => settings.carousel, val => { | |||
if (val) { | |||
timer.value = setInterval(() => { | |||
handlePageChange(pages[(pages.indexOf(currentPage.value) + 1) % pages.length]) | |||
}, settings.carouselTime); | |||
}, settings.carouselTime * 1000); | |||
return; | |||
} | |||
clearInterval(timer.value); | |||
@@ -38,7 +38,7 @@ watch(() => settings.carouselTime, val => { | |||
if (timer.value) clearInterval(timer.value); | |||
timer.value = setInterval(() => { | |||
handlePageChange(pages[(pages.indexOf(currentPage.value) + 1) % pages.length]) | |||
}, val); | |||
}, val * 1000); | |||
} | |||
}) | |||
@@ -62,7 +62,7 @@ const pathMap = { | |||
</script> | |||
<template> | |||
<div class="main-container"> | |||
<div id="main-container" class="main-container"> | |||
<DatetimeTool v-if="currentPage !== 'announcement'" /> | |||
<Tools v-if="currentPage !== 'announcement'" /> | |||
<AppHeader v-if="currentPage !== 'announcement'" /> | |||
@@ -1,8 +1,13 @@ | |||
<script setup> | |||
import { ref } from 'vue'; | |||
import { useSettings } from '../store/settings' | |||
const emit = defineEmits(["close"]); | |||
const { settings, changeScale } = useSettings(); | |||
const store = useSettings(); | |||
const settings = ref(store.settings); | |||
store.$subscribe((mutation, state) => { | |||
settings.value.fullscreen = state.settings.fullscreen; | |||
}) | |||
function handleCancel() { | |||
emit('close') | |||
@@ -10,7 +15,11 @@ function handleCancel() { | |||
function handleConfirm() { | |||
// alert(JSON.stringify(settings, null, 2)) | |||
changeScale(settings.resolution.width, settings.resolution.height) | |||
// changeScale(settings.resolution.width, settings.resolution.height) | |||
if (settings.value.resolution.width < 480) store.settings.resolution.width = 480; | |||
if (settings.value.resolution.width > 7680) store.settings.resolution.width = 7680; | |||
if (settings.value.resolution.height < 270) store.settings.resolution.height = 270; | |||
if (settings.value.resolution.height > 4320) store.settings.resolution.height = 4320; | |||
emit('close') | |||
} | |||
</script> | |||
@@ -26,9 +35,9 @@ function handleConfirm() { | |||
</div> | |||
<div class="form-item"> | |||
<label for="resolution1">分辨率</label> | |||
<input id="resolution1" type="number" v-model="settings.resolution.width" /> | |||
<input id="resolution1" type="number" min="480" max="7680" v-model="settings.resolution.width" /> | |||
<span>X</span> | |||
<input id="resolution2" type="number" v-model="settings.resolution.height" /> | |||
<input id="resolution2" type="number" min="270" max="4320" v-model="settings.resolution.height" /> | |||
<span>px</span> | |||
</div> | |||
<div class="form-item selector"> | |||
@@ -173,11 +182,14 @@ button { | |||
} | |||
.modal { | |||
position: fixed; | |||
/* position: fixed; | |||
height: 1080px; | |||
width: 1920px; */ | |||
position: absolute; | |||
height: 100%; | |||
width: 100%; | |||
left: 0; | |||
top: 0; | |||
height: 1080px; | |||
width: 1920px; | |||
background: #0003; | |||
backdrop-filter: blur(3px); | |||
z-index: 999; | |||
@@ -5,31 +5,37 @@ import IconExchange from "../assets/menu_icon/IconExchange.vue"; | |||
import IconSetting from "../assets/menu_icon/IconSetting.vue"; | |||
import SettingDialogVue from "./SettingDialog.vue"; | |||
import { useSettings } from '../store/settings'; | |||
const { settings } = useSettings(); | |||
const store = useSettings(); | |||
const settings = ref(store.settings) | |||
store.$subscribe((_, state) => { | |||
settings.value.carousel = state.settings.carousel; | |||
}) | |||
const visible = ref(false); | |||
function toHome() { | |||
document.location.href = '/1-1' | |||
// document.location.href = '/1-1' | |||
document.location.reload() | |||
} | |||
function showDialog() { | |||
visible.value = true; | |||
} | |||
function toggleLunbo() { | |||
settings.carousel = !settings.carousel; | |||
settings.value.carousel = !settings.value.carousel; | |||
} | |||
</script> | |||
<template> | |||
<div class="tools"> | |||
<div id="tools-bar" class="tools"> | |||
<button @click="toHome"> | |||
<IconBack /> | |||
</button> | |||
<button @click="showDialog"> | |||
<IconSetting /> | |||
</button> | |||
<button @click="toggleLunbo"> | |||
<IconExchange /> | |||
<button style="position: relative;" @click="toggleLunbo"> | |||
<span v-if="settings.carousel" | |||
style="color: #fffa; font-family: 'Courier New', Courier, monospace; font-weight:600; font-size: 22px; user-select: none; position: absolute; line-height: 52px; text-align: center;"> | |||
{{ settings.carouselTime }}S</span> | |||
<IconExchange :color="settings.carousel ? '#03356a' : '#50A1EC'" /> | |||
</button> | |||
</div> | |||
<SettingDialogVue v-if="visible" @close="visible = false;" /> | |||
@@ -78,4 +84,5 @@ button:hover svg #back-btn, | |||
button:hover svg #setting-btn, | |||
button:hover svg #switch-btn { | |||
fill: #b1daff !important; | |||
}</style> | |||
} | |||
</style> |
@@ -40,7 +40,7 @@ const handleClose = () => { | |||
<div class="announcement-page"> | |||
<h1 class="announcement-title">公告栏</h1> | |||
<main class="announcement-content"> | |||
<ScrollText :vertical="true" :duration="10" :pause-on-hover="true"> | |||
<ScrollText :vertical="true" :duration="50" :pause-on-hover="true"> | |||
<div v-html="vertical_content"></div> | |||
</ScrollText> | |||
</main> | |||
@@ -60,7 +60,7 @@ const handleClose = () => { | |||
> | |||
<IconBack color="#f00"/> | |||
</button> | |||
<ScrollText> {{ horizontal_content }} </ScrollText> | |||
<ScrollText :duration="50"> {{ horizontal_content }} </ScrollText> | |||
</div> | |||
</div> | |||
</template> | |||
@@ -2,48 +2,51 @@ import { defineStore } from "pinia"; | |||
import { ref, watch } from "vue"; | |||
export const useSettings = defineStore("settings", () => { | |||
const settings = ref({ | |||
resolution: { | |||
width: 1920, | |||
height: 1080, | |||
}, | |||
carousel: false, | |||
carouselTime: 10000, // s | |||
fullscreen: false, | |||
eqStatus: true, | |||
}); | |||
function changeScale(width, height) { | |||
const xScale = width / 1920; | |||
const yScale = height / 1080; | |||
const style = { | |||
transform: `scale(${xScale}, ${yScale})`, | |||
transformOrigin: "top left", | |||
}; | |||
document.documentElement.style.transform = style.transform; | |||
document.documentElement.style.transformOrigin = style.transformOrigin; | |||
} | |||
const initialSettings = localStorage.getItem("settings"); | |||
const settings = ref( | |||
initialSettings | |||
? JSON.parse(initialSettings) | |||
: { | |||
resolution: { | |||
width: 1920, | |||
height: 1080, | |||
}, | |||
carousel: false, | |||
carouselTime: 10, // s | |||
fullscreen: false, | |||
eqStatus: true, | |||
} | |||
); | |||
function resetScale() { | |||
document.documentElement.style.transform = "initial"; | |||
document.documentElement.style.transformOrigin = "initial"; | |||
} | |||
const clearFullscreenFlag = (e) => { | |||
if (!document.fullscreenElement) { | |||
settings.value.fullscreen = false; | |||
} | |||
}; | |||
watch( | |||
() => settings.value.fullscreen, | |||
(val) => { | |||
const mainContainer = document.getElementById("main-container"); | |||
if (val) { | |||
document.documentElement.requestFullscreen().then(() => { | |||
document.documentElement.style.width = "100vw"; | |||
document.documentElement.style.height = "100vh"; | |||
changeScale( | |||
document.documentElement.clientWidth, | |||
document.documentElement.clientHeight | |||
); | |||
mainContainer.requestFullscreen().then(() => { | |||
document.removeEventListener("fullscreenchange", clearFullscreenFlag); | |||
document.addEventListener("fullscreenchange", clearFullscreenFlag); | |||
}); | |||
return; | |||
} | |||
document.exitFullscreen().then(resetScale); | |||
if (document.fullscreenElement) document.exitFullscreen(); | |||
} | |||
); | |||
watch( | |||
() => settings.value, | |||
(val) => { | |||
localStorage.setItem("settings", JSON.stringify(val)); | |||
}, | |||
{ | |||
immediate: true, | |||
deep: true, | |||
} | |||
); | |||
@@ -70,3 +73,19 @@ export const useSettings = defineStore("settings", () => { | |||
} | |||
return { settings, updateSettings, rewriteSettings, changeScale }; | |||
}); | |||
function changeScale(elm, width, height) { | |||
const xScale = width / 1920; | |||
const yScale = height / 1080; | |||
const style = { | |||
transform: `scale(${xScale}, ${yScale}) !important`, | |||
transformOrigin: "top left", | |||
}; | |||
elm.style.transform = style.transform; | |||
elm.style.transformOrigin = style.transformOrigin; | |||
} | |||
function resetScale(elm) { | |||
elm.style.transform = "initial"; | |||
elm.style.transformOrigin = "initial"; | |||
} |