mirror of
https://github.com/hpware/news-analyze.git
synced 2025-06-23 13:04:23 +00:00
feat: enhance UI components with improved styles and new windows; add error handling and copyright information
This commit is contained in:
parent
eaa9b15b2d
commit
1065a982b0
10 changed files with 142 additions and 78 deletions
|
@ -76,13 +76,13 @@ const stopDrag = () => {
|
|||
<div class="flex flex-row gap-1">
|
||||
<button
|
||||
@click="emit('min')"
|
||||
class="p-1 hover:bg-gray-300 dark:hover:bg-gray-600 rounded"
|
||||
class="p-1 hover:bg-gray-300 dark:hover:bg-gray-600 rounded transition duration-200"
|
||||
>
|
||||
━
|
||||
</button>
|
||||
<button
|
||||
@click="emit('maximize')"
|
||||
class="p-1 hover:bg-gray-300 dark:hover:bg-gray-600 rounded"
|
||||
class="p-1 hover:bg-gray-300 dark:hover:bg-gray-600 rounded transition duration-200"
|
||||
>
|
||||
⬜
|
||||
</button>
|
||||
|
|
13
components/app/info/copyright.vue
Normal file
13
components/app/info/copyright.vue
Normal file
|
@ -0,0 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
<template>
|
||||
<div class="gap-2 flex flex-row">
|
||||
<!--版權資訊-->
|
||||
<span class="text-sm">1.0.0</span>
|
||||
<span class="text-sm">|</span>
|
||||
<span class="text-sm">MIT {{ t("app.license") }}</span>
|
||||
<span class="text-sm">|</span>
|
||||
<span class="text-sm">{{ new Date().getFullYear() }} © yh</span>
|
||||
</div>
|
||||
</template>
|
2
components/app/windows/about.vue
Normal file
2
components/app/windows/about.vue
Normal file
|
@ -0,0 +1,2 @@
|
|||
<template>
|
||||
</template>
|
10
components/app/windows/error404.vue
Normal file
10
components/app/windows/error404.vue
Normal file
|
@ -0,0 +1,10 @@
|
|||
<template>
|
||||
<div class="justify-center align-center text-center flex flex-col">
|
||||
<span class="text-7xl m-4 m-1 mb-0 text-center align-center justify-center"
|
||||
>404</span
|
||||
>
|
||||
<span class="text-2xl text-center align-center justify-center"
|
||||
>User interface Not Found</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
|
@ -43,7 +43,7 @@ try {
|
|||
<ul v-for="ititit in itit">
|
||||
<li v-if="ititit.content?.[0].content[0] !== item.title">
|
||||
-
|
||||
<a :href="ititit.content?.[0].attributes?.href">{{
|
||||
<a :href="ititit.content?.[0].attributes?.href" target="_blank">{{
|
||||
ititit.content?.[0].content[0]
|
||||
}}</a>
|
||||
-
|
||||
|
|
|
@ -20,7 +20,7 @@ const toggleDropdown = () => {
|
|||
class="fixed top-0 inset-x-0 bg-[#81611a]/70 backdrop-blur-sm h-[55px] flex align-center items-center flex-row text-white pl-4 gap-x-5 justify-between z-50 rounded-3xl m-2"
|
||||
>
|
||||
<div class="text-3xl text-bold">
|
||||
<NuxtLink :to="localePath('home')" ref="title">BlindSpec</NuxtLink>
|
||||
<NuxtLink :to="localePath('home')" ref="title">{{ t("core.sitename") }}</NuxtLink>
|
||||
</div>
|
||||
<div
|
||||
class="text-[0.9em] left-1/2 absolute transform -translate-x-1/2 space-x-4 items-center"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"nonMoving": "嗨!這是你的",
|
||||
"moving": {
|
||||
"newsPlatform": "新聞平台",
|
||||
"miniWikipedia": "米你維基百科",
|
||||
"miniWikipedia": "迷你維基百科",
|
||||
"newsComparePlatform": "新聞觀點比對平台"
|
||||
},
|
||||
"startusing": "開始使用!",
|
||||
|
|
|
@ -42,8 +42,8 @@ export default defineNuxtConfig({
|
|||
},
|
||||
|
||||
site: {
|
||||
url: "https://news.yuanhau.com",
|
||||
title: "BlindSpec",
|
||||
url: "https://news.yuanhau.com/",
|
||||
title: "新聞盲點平台",
|
||||
description: "",
|
||||
},
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "BlindSpec",
|
||||
"name": "blindspec",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
|
|
@ -30,6 +30,8 @@ gsap.registerPlugin(TextPlugin);
|
|||
import LoginWindow from "~/components/app/windows/login.vue";
|
||||
import HotNewsWindow from "~/components/app/windows/hotnews.vue";
|
||||
import SourcesWindow from "~/components/app/windows/sources.vue";
|
||||
import AboutWindow from "~/components/app/windows/about.vue";
|
||||
import Error404Window from "~/components/app/windows/error404.vue";
|
||||
|
||||
// Import Shadcn/UI components
|
||||
import AlertComponent from "~/components/ui/alert/Alert.vue";
|
||||
|
@ -62,6 +64,59 @@ const langMenuOpen = ref(false);
|
|||
const lang = ref(locale.value);
|
||||
const alertOpen = ref(false);
|
||||
const currentNavBar = ref<currentNavBarInterface[]>([]);
|
||||
const bootingAnimation = ref(true);
|
||||
const bypassBoot = ref(false);
|
||||
const activeWindows = ref<associAppWindowInterface>([]);
|
||||
const openApp = ref();
|
||||
const openAppId = ref();
|
||||
const openAppNameQuery = ref();
|
||||
const currentOpenAppId = ref(0);
|
||||
const progress = ref(0);
|
||||
|
||||
|
||||
// Key Data
|
||||
const menuItems = [
|
||||
{ name: t("app.hotnews"), windowName: "hotnews" },
|
||||
{ name: t("app.news"), windowName: "news" },
|
||||
{ name: t("app.sources"), windowName: "sources" },
|
||||
{ name: t("app.starred"), windowName: "starred" },
|
||||
{ name: t("app.about"), windowName: "about" },
|
||||
{ name: t("app.settings"), windowName: "settings" },
|
||||
{ name: t("app.login"), windowName: "login" },
|
||||
{ name: t("app.leave"), windowName: "leave" },
|
||||
];
|
||||
|
||||
const associAppWindow = [
|
||||
{
|
||||
name: "hotnews",
|
||||
id: "1",
|
||||
title: t("app.hotnews"),
|
||||
component: HotNewsWindow,
|
||||
width: "700px",
|
||||
height: "500px",
|
||||
},
|
||||
{ name: "login", id: "2", title: t("app.login"), component: LoginWindow },
|
||||
{
|
||||
name: "sources",
|
||||
id: "3",
|
||||
title: t("app.sources"),
|
||||
component: SourcesWindow,
|
||||
},
|
||||
{ name: "about", id: "4", title: t("app.about"), component: AboutWindow },
|
||||
{
|
||||
name: "settings",
|
||||
id: "5",
|
||||
title: t("app.settings"),
|
||||
component: Error404Window,
|
||||
},
|
||||
{ name: "news", id: "6", title: t("app.news"), component: Error404Window },
|
||||
{
|
||||
name: "starred",
|
||||
id: "7",
|
||||
title: t("app.starred"),
|
||||
component: Error404Window,
|
||||
},
|
||||
];
|
||||
|
||||
// Date
|
||||
const currentDate = ref(
|
||||
|
@ -105,14 +160,6 @@ const unMinWindow = (windowName?: string) => {
|
|||
};
|
||||
|
||||
// menus
|
||||
const menuItems = [
|
||||
{ name: "Hot News", windowName: "hotnews" },
|
||||
{ name: "News", windowName: "news" },
|
||||
{ name: "Sources", windowName: "sources" },
|
||||
{ name: "About This Website", windowName: "about" },
|
||||
{ name: "Settings", windowName: "settings" },
|
||||
{ name: "Leave", windowName: "leave" },
|
||||
];
|
||||
const toggleMenu = () => {
|
||||
menuOpen.value = !menuOpen.value;
|
||||
};
|
||||
|
@ -121,14 +168,7 @@ const toggleLangMenu = () => {
|
|||
langMenuOpen.value = !langMenuOpen.value;
|
||||
};
|
||||
|
||||
// values
|
||||
const activeWindows = ref<associAppWindowInterface>([]);
|
||||
|
||||
// ?opemapp= component
|
||||
const openApp = ref();
|
||||
const openAppId = ref();
|
||||
const openAppNameQuery = ref();
|
||||
|
||||
// ?openapp= component
|
||||
onMounted(async () => {
|
||||
openApp.value = route.query.openapp;
|
||||
openAppId.value = route.query.id;
|
||||
|
@ -137,25 +177,6 @@ onMounted(async () => {
|
|||
}
|
||||
});
|
||||
|
||||
const associAppWindow = [
|
||||
{
|
||||
name: "hotnews",
|
||||
id: "1",
|
||||
title: "Hot News",
|
||||
component: HotNewsWindow,
|
||||
width: "700px",
|
||||
height: "500px",
|
||||
},
|
||||
{ name: "login", id: "2", title: t("app.login"), component: LoginWindow },
|
||||
{
|
||||
name: "sources",
|
||||
id: "3",
|
||||
title: t("app.sources"),
|
||||
component: SourcesWindow,
|
||||
},
|
||||
];
|
||||
|
||||
const currentOpenAppId = ref(0);
|
||||
|
||||
const findAndOpenWindow = (windowName: string) => {
|
||||
const app = associAppWindow.find((app) => app.name === windowName);
|
||||
|
@ -168,6 +189,14 @@ const findAndOpenWindow = (windowName: string) => {
|
|||
return;
|
||||
}
|
||||
|
||||
// Prevent dual about
|
||||
if (
|
||||
windowName === "about" &&
|
||||
activeWindows.value.some((window) => window.name === "about")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (app) {
|
||||
// Use shallowRef for better performance with components
|
||||
const windowComponent = shallowRef(app.component);
|
||||
|
@ -201,13 +230,50 @@ const topWindow = (windowId: string) => {
|
|||
}
|
||||
};
|
||||
|
||||
// Title
|
||||
useSeoMeta({
|
||||
title: "hi" + " - Desktop",
|
||||
});
|
||||
|
||||
// Booting animation
|
||||
onMounted(() => {
|
||||
// booting animation bypass
|
||||
const bootingHeaderParams = route.query.bypass;
|
||||
if (bootingHeaderParams) {
|
||||
bypassBoot.value = true;
|
||||
console.log("Bypass booting animation");
|
||||
}
|
||||
if (!bypassBoot.value) {
|
||||
gsap.to(popMessage.value, {
|
||||
duration: 0.5,
|
||||
text: t("app.booting"),
|
||||
ease: "none",
|
||||
});
|
||||
setTimeout(() => {
|
||||
bootingAnimation.value = false;
|
||||
}, 2000);
|
||||
} else {
|
||||
bootingAnimation.value = false;
|
||||
}
|
||||
})
|
||||
|
||||
watchEffect((cleanupFn) => {
|
||||
const timer = setTimeout(() => progress.value = 100, 500)
|
||||
cleanupFn(() => clearTimeout(timer))
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div v-if="bootingAnimation">
|
||||
<div class="flex flex-col justify-center align-center text-center absolute w-full h-screen inset-0 ">
|
||||
<Progress v-model="progress" class="w-3/5 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2" />
|
||||
<br/>
|
||||
<span class="text-xl text-bold mt-3"
|
||||
>Launching your fancy desktop...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="absolute inset-x-0 flex flex-row px-2 py-1 bg-[#7D7C7C]/70 text-white justify-between align-center text-center z-50"
|
||||
v-else
|
||||
>
|
||||
<!--Menu container-->
|
||||
<div class="flex flex-row g-2 text-gray-400 text-white z-9999">
|
||||
|
@ -240,9 +306,17 @@ useSeoMeta({
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row gap-5">
|
||||
<button
|
||||
class="p-1 hover:text-blue-200 transition-all duration-100 hover:bg-gray-500 rounded"
|
||||
@click="toggleLangMenu"
|
||||
>
|
||||
{{ t("localeflag") }}
|
||||
</button>
|
||||
<div class="text-center align-middle justify-center text-white">
|
||||
{{ currentDate }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full h-[2.5em]"></div>
|
||||
<!--Menu-->
|
||||
|
@ -291,39 +365,4 @@ useSeoMeta({
|
|||
</DraggableWindow>
|
||||
</div>
|
||||
</Transition>
|
||||
<!--Footer-->
|
||||
<div
|
||||
class="absolute w-[calc(100% - 5px)] inset-x-0 bottom-0 mx-[1.5px] p-3 justify-between align-center flex flex-row z-0"
|
||||
>
|
||||
<div class="">
|
||||
<!--Lang-->
|
||||
<span>Lang: </span>
|
||||
<span class="text-lg">{{ t("localeflag") }}</span
|
||||
>
|
||||
<button
|
||||
class="w-4 h-4 hover:text-blue-200 transition-all duration-100"
|
||||
@click="toggleLangMenu"
|
||||
>
|
||||
<LanguageIcon />
|
||||
</button>
|
||||
</div>
|
||||
<div class="gap-2 flex flex-row">
|
||||
<!--版權資訊-->
|
||||
<span class="text-sm">1.0.0</span>
|
||||
<span class="text-sm">|</span>
|
||||
<span class="text-sm">MIT {{ t("app.license") }}</span>
|
||||
<span class="text-sm">|</span>
|
||||
<span class="text-sm">{{ new Date().getFullYear() }} © yh</span>
|
||||
</div>
|
||||
<div class="">
|
||||
<button
|
||||
@click="openWindow('login')"
|
||||
class="w-8 h-8 text-gray-400 flex flex-row"
|
||||
>
|
||||
<UserIcon
|
||||
class="w-8 h-8 text-gray-400 hover:text-blue-500 transition-all duration-100"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue