@@ -11,6 +11,7 @@ | |||||
"echarts": "^5.4.3", | "echarts": "^5.4.3", | ||||
"element-plus": "^2.4.4", | "element-plus": "^2.4.4", | ||||
"pinia": "^2.1.7", | "pinia": "^2.1.7", | ||||
"screenfull": "^6.0.2", | |||||
"vue": "^3.3.11", | "vue": "^3.3.11", | ||||
"vue3-marquee": "^4.1.0" | "vue3-marquee": "^4.1.0" | ||||
}, | }, | ||||
@@ -1123,6 +1124,14 @@ | |||||
"fsevents": "~2.3.2" | "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": { | "node_modules/source-map-js": { | ||||
"version": "1.0.2", | "version": "1.0.2", | ||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", | ||||
@@ -1888,6 +1897,11 @@ | |||||
"fsevents": "~2.3.2" | "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": { | "source-map-js": { | ||||
"version": "1.0.2", | "version": "1.0.2", | ||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", | ||||
@@ -12,6 +12,7 @@ | |||||
"echarts": "^5.4.3", | "echarts": "^5.4.3", | ||||
"element-plus": "^2.4.4", | "element-plus": "^2.4.4", | ||||
"pinia": "^2.1.7", | "pinia": "^2.1.7", | ||||
"screenfull": "^6.0.2", | |||||
"vue": "^3.3.11", | "vue": "^3.3.11", | ||||
"vue3-marquee": "^4.1.0" | "vue3-marquee": "^4.1.0" | ||||
}, | }, | ||||
@@ -26,7 +26,7 @@ watch(() => settings.carousel, val => { | |||||
if (val) { | if (val) { | ||||
timer.value = setInterval(() => { | timer.value = setInterval(() => { | ||||
handlePageChange(pages[(pages.indexOf(currentPage.value) + 1) % pages.length]) | handlePageChange(pages[(pages.indexOf(currentPage.value) + 1) % pages.length]) | ||||
}, settings.carouselTime); | |||||
}, settings.carouselTime * 1000); | |||||
return; | return; | ||||
} | } | ||||
clearInterval(timer.value); | clearInterval(timer.value); | ||||
@@ -38,7 +38,7 @@ watch(() => settings.carouselTime, val => { | |||||
if (timer.value) clearInterval(timer.value); | if (timer.value) clearInterval(timer.value); | ||||
timer.value = setInterval(() => { | timer.value = setInterval(() => { | ||||
handlePageChange(pages[(pages.indexOf(currentPage.value) + 1) % pages.length]) | handlePageChange(pages[(pages.indexOf(currentPage.value) + 1) % pages.length]) | ||||
}, val); | |||||
}, val * 1000); | |||||
} | } | ||||
}) | }) | ||||
@@ -62,7 +62,7 @@ const pathMap = { | |||||
</script> | </script> | ||||
<template> | <template> | ||||
<div class="main-container"> | |||||
<div id="main-container" class="main-container"> | |||||
<DatetimeTool v-if="currentPage !== 'announcement'" /> | <DatetimeTool v-if="currentPage !== 'announcement'" /> | ||||
<Tools v-if="currentPage !== 'announcement'" /> | <Tools v-if="currentPage !== 'announcement'" /> | ||||
<AppHeader v-if="currentPage !== 'announcement'" /> | <AppHeader v-if="currentPage !== 'announcement'" /> | ||||
@@ -1,8 +1,13 @@ | |||||
<script setup> | <script setup> | ||||
import { ref } from 'vue'; | |||||
import { useSettings } from '../store/settings' | import { useSettings } from '../store/settings' | ||||
const emit = defineEmits(["close"]); | 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() { | function handleCancel() { | ||||
emit('close') | emit('close') | ||||
@@ -10,7 +15,11 @@ function handleCancel() { | |||||
function handleConfirm() { | function handleConfirm() { | ||||
// alert(JSON.stringify(settings, null, 2)) | // 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') | emit('close') | ||||
} | } | ||||
</script> | </script> | ||||
@@ -26,9 +35,9 @@ function handleConfirm() { | |||||
</div> | </div> | ||||
<div class="form-item"> | <div class="form-item"> | ||||
<label for="resolution1">分辨率</label> | <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> | <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> | <span>px</span> | ||||
</div> | </div> | ||||
<div class="form-item selector"> | <div class="form-item selector"> | ||||
@@ -173,11 +182,14 @@ button { | |||||
} | } | ||||
.modal { | .modal { | ||||
position: fixed; | |||||
/* position: fixed; | |||||
height: 1080px; | |||||
width: 1920px; */ | |||||
position: absolute; | |||||
height: 100%; | |||||
width: 100%; | |||||
left: 0; | left: 0; | ||||
top: 0; | top: 0; | ||||
height: 1080px; | |||||
width: 1920px; | |||||
background: #0003; | background: #0003; | ||||
backdrop-filter: blur(3px); | backdrop-filter: blur(3px); | ||||
z-index: 999; | z-index: 999; | ||||
@@ -5,31 +5,37 @@ import IconExchange from "../assets/menu_icon/IconExchange.vue"; | |||||
import IconSetting from "../assets/menu_icon/IconSetting.vue"; | import IconSetting from "../assets/menu_icon/IconSetting.vue"; | ||||
import SettingDialogVue from "./SettingDialog.vue"; | import SettingDialogVue from "./SettingDialog.vue"; | ||||
import { useSettings } from '../store/settings'; | 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); | const visible = ref(false); | ||||
function toHome() { | function toHome() { | ||||
document.location.href = '/1-1' | |||||
// document.location.href = '/1-1' | |||||
document.location.reload() | |||||
} | } | ||||
function showDialog() { | function showDialog() { | ||||
visible.value = true; | visible.value = true; | ||||
} | } | ||||
function toggleLunbo() { | function toggleLunbo() { | ||||
settings.carousel = !settings.carousel; | |||||
settings.value.carousel = !settings.value.carousel; | |||||
} | } | ||||
</script> | </script> | ||||
<template> | <template> | ||||
<div class="tools"> | |||||
<div id="tools-bar" class="tools"> | |||||
<button @click="toHome"> | <button @click="toHome"> | ||||
<IconBack /> | <IconBack /> | ||||
</button> | </button> | ||||
<button @click="showDialog"> | <button @click="showDialog"> | ||||
<IconSetting /> | <IconSetting /> | ||||
</button> | </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> | </button> | ||||
</div> | </div> | ||||
<SettingDialogVue v-if="visible" @close="visible = false;" /> | <SettingDialogVue v-if="visible" @close="visible = false;" /> | ||||
@@ -78,4 +84,5 @@ button:hover svg #back-btn, | |||||
button:hover svg #setting-btn, | button:hover svg #setting-btn, | ||||
button:hover svg #switch-btn { | button:hover svg #switch-btn { | ||||
fill: #b1daff !important; | fill: #b1daff !important; | ||||
}</style> | |||||
} | |||||
</style> |
@@ -40,7 +40,7 @@ const handleClose = () => { | |||||
<div class="announcement-page"> | <div class="announcement-page"> | ||||
<h1 class="announcement-title">公告栏</h1> | <h1 class="announcement-title">公告栏</h1> | ||||
<main class="announcement-content"> | <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> | <div v-html="vertical_content"></div> | ||||
</ScrollText> | </ScrollText> | ||||
</main> | </main> | ||||
@@ -60,7 +60,7 @@ const handleClose = () => { | |||||
> | > | ||||
<IconBack color="#f00"/> | <IconBack color="#f00"/> | ||||
</button> | </button> | ||||
<ScrollText> {{ horizontal_content }} </ScrollText> | |||||
<ScrollText :duration="50"> {{ horizontal_content }} </ScrollText> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</template> | </template> | ||||
@@ -2,48 +2,51 @@ import { defineStore } from "pinia"; | |||||
import { ref, watch } from "vue"; | import { ref, watch } from "vue"; | ||||
export const useSettings = defineStore("settings", () => { | 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( | watch( | ||||
() => settings.value.fullscreen, | () => settings.value.fullscreen, | ||||
(val) => { | (val) => { | ||||
const mainContainer = document.getElementById("main-container"); | |||||
if (val) { | 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; | 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 }; | 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"; | |||||
} |