mirror of
https://github.com/hpware/news-analyze.git
synced 2025-06-23 15:51:01 +08:00
feat: integrate animate.css for animations, enhance layout, and improve localization files
This commit is contained in:
parent
95661e908a
commit
2f20d49091
4
app.vue
4
app.vue
@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||
import "animate.css";
|
||||
const { t } = useI18n();
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<!--A yhw_tw project-->
|
||||
<NuxtLayout>
|
||||
<NuxtPage/>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</template>
|
||||
|
3
bun.lock
3
bun.lock
@ -12,6 +12,7 @@
|
||||
"@nuxtjs/tailwindcss": "6.14.0",
|
||||
"@tailwindcss/vite": "^4.1.5",
|
||||
"@uploadthing/nuxt": "^7.1.7",
|
||||
"animate.css": "^4.1.1",
|
||||
"bootstrap-icons": "^1.12.1",
|
||||
"gsap": "^3.13.0",
|
||||
"nuxt": "^3.17.2",
|
||||
@ -605,6 +606,8 @@
|
||||
|
||||
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
|
||||
|
||||
"animate.css": ["animate.css@4.1.1", "", {}, "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
@ -1,3 +1,9 @@
|
||||
<template>
|
||||
|
||||
<div
|
||||
class="flex flex-row justify-center align-center text-center absolute inset-x-0"
|
||||
>
|
||||
<span class="text-xs m-4"
|
||||
>{{ new Date().getFullYear() }} © 吳元皓</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
@ -1,62 +1,91 @@
|
||||
<script setup lang="ts">
|
||||
import { gsap } from 'gsap';
|
||||
import { ScrambleTextPlugin } from 'gsap/dist/ScrambleTextPlugin';
|
||||
gsap.registerPlugin(ScrambleTextPlugin)
|
||||
import { gsap } from "gsap";
|
||||
import { ScrambleTextPlugin } from "gsap/dist/ScrambleTextPlugin";
|
||||
gsap.registerPlugin(ScrambleTextPlugin);
|
||||
|
||||
const { t, locale, locales } = useI18n();
|
||||
const switchLocalePath = useSwitchLocalePath()
|
||||
const switchLocalePath = useSwitchLocalePath();
|
||||
|
||||
const dropdownOpen = ref(false);
|
||||
const title = ref(null);
|
||||
|
||||
const availableLocales = computed(() => {
|
||||
return locales.value.filter(i => i.code !== locale.value)
|
||||
})
|
||||
return locales.value.filter((i) => i.code !== locale.value);
|
||||
});
|
||||
|
||||
const toggleDropdown = () => {
|
||||
dropdownOpen.value = !dropdownOpen.value;
|
||||
}
|
||||
};
|
||||
|
||||
const runAnimation = () => {
|
||||
gsap.to(title.value, {
|
||||
duration: 1,
|
||||
scrambleText: "BlindSpec",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<!--Spent too much time trying to set a Navbar....-->
|
||||
<div class="fixed top-0 inset-x-0 bg-[#81611a]/70 backdrop-blur-sm h-[55px] flex align-center flex-row text-white pl-4 pt-2 gap-x-5 justify-between z-50 rounded-3xl m-2">
|
||||
<div
|
||||
class="fixed top-0 inset-x-0 bg-[#81611a]/70 backdrop-blur-sm h-[55px] flex align-center flex-row text-white pl-4 pt-2 gap-x-5 justify-between z-50 rounded-3xl m-2"
|
||||
>
|
||||
<div class="text-3xl text-bold">
|
||||
<!--Use mouseenter instead of hover-->
|
||||
<a href="/" @mouseenter="runAnimation" ref="title">
|
||||
BlindSpec
|
||||
</a>
|
||||
<a href="/" @mouseenter="runAnimation" ref="title"> BlindSpec </a>
|
||||
</div>
|
||||
<div class="text-[0.9em] text-center align-center">
|
||||
<a href="/" class="hover:text-blue-500 cursor-pointer transiton-all duration-100">{{ t("nav.home") }}</a>
|
||||
<a
|
||||
href="/"
|
||||
class="hover:text-blue-500 cursor-pointer transiton-all duration-100"
|
||||
>{{ t("nav.home") }}</a
|
||||
>
|
||||
|
||||
<a href="/dailybriefing" class="hover:text-blue-500 cursor-pointer transiton-all duration-100">{{ t("nav.dailybriefing") }}</a>
|
||||
<a
|
||||
href="/dailybriefing"
|
||||
class="hover:text-blue-500 cursor-pointer transiton-all duration-100"
|
||||
>{{ t("nav.dailybriefing") }}</a
|
||||
>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<button @click="toggleDropdown"
|
||||
class="flex items-center space-x-2 px-4 py-2 rounded hover:bg-gray-900 transition-all duration-100">
|
||||
<button
|
||||
@click="toggleDropdown"
|
||||
class="flex items-center space-x-2 px-4 py-2 rounded hover:bg-gray-900 transition-all duration-100"
|
||||
>
|
||||
<span>{{ locale }}</span>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M19 9l-7 7-7-7"/>
|
||||
<svg
|
||||
class="w-4 h-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 9l-7 7-7-7"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div v-if="dropdownOpen"
|
||||
class="absolute top-full left-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1">
|
||||
<a v-for="loc in availableLocales"
|
||||
<Transition
|
||||
enter-active-class="animate__animated animate__fadeInDown animate__faster"
|
||||
leave-active-class="animate__animated animate__fadeOutUp animate__faster"
|
||||
>
|
||||
<div
|
||||
v-if="dropdownOpen"
|
||||
class="absolute top-full right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1"
|
||||
>
|
||||
<a
|
||||
v-for="loc in availableLocales"
|
||||
:key="loc.code"
|
||||
:href="switchLocalePath(loc.code)"
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
|
||||
v-on:click="dropdownOpen = false"
|
||||
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-all duration-100"
|
||||
>
|
||||
{{ loc.name || loc.code }}
|
||||
</a>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
4
i18n/i18n.config.ts
Normal file
4
i18n/i18n.config.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export default defineI18nConfig(() => ({
|
||||
legacy: false,
|
||||
locale: "en",
|
||||
}));
|
@ -3,7 +3,8 @@
|
||||
"sitename": "BlindSpec"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Home"
|
||||
"home": "Home",
|
||||
"dailybriefing": "Daily Briefing"
|
||||
},
|
||||
"dailybriefing": "Daily Briefing",
|
||||
"Welcome": "Welcome",
|
||||
|
@ -1,4 +0,0 @@
|
||||
export default defineI18nConfig(() => ({
|
||||
legacy: false,
|
||||
locale: 'en',
|
||||
}))
|
@ -3,7 +3,8 @@
|
||||
"sitename": "新聞盲點平台"
|
||||
},
|
||||
"nav": {
|
||||
"home": "首頁"
|
||||
"home": "首頁",
|
||||
"dailybriefing": "今日報導"
|
||||
},
|
||||
"dailybriefing": "今日報導",
|
||||
"Welcome": "歡迎",
|
||||
|
@ -1,15 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import Navigation from '~/components/navigation.vue';
|
||||
import Navigation from "~/components/navigation.vue";
|
||||
import Footer from "~/components/footer.vue";
|
||||
</script>
|
||||
<template>
|
||||
<nav>
|
||||
<Navigation/>
|
||||
<Navigation />
|
||||
</nav>
|
||||
<main class="pt-[60px]">
|
||||
<slot/>
|
||||
<slot />
|
||||
</main>
|
||||
<footer>
|
||||
<Footer/>
|
||||
<Footer />
|
||||
</footer>
|
||||
</template>
|
@ -1,15 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import Navigation from '~/components/navigation.vue';
|
||||
import Navigation from "~/components/navigation.vue";
|
||||
import Footer from "~/components/footer.vue";
|
||||
</script>
|
||||
<template>
|
||||
<nav>
|
||||
<Navigation/>
|
||||
<Navigation />
|
||||
</nav>
|
||||
<main class="pt-[60px]">
|
||||
<slot/>
|
||||
<slot />
|
||||
</main>
|
||||
<footer>
|
||||
<Footer/>
|
||||
<Footer />
|
||||
</footer>
|
||||
</template>
|
@ -1,19 +1,25 @@
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2025-05-06',
|
||||
compatibilityDate: "2025-05-06",
|
||||
devtools: { enabled: true },
|
||||
routeRules: {
|
||||
"/": { redirect: "/home"},
|
||||
"/zh_tw": { redirect: "/zh_tw/home"},
|
||||
} ,
|
||||
css: ['~/styles/main.css'],
|
||||
modules: ['@nuxt/image', '@nuxtjs/robots', '@nuxtjs/seo', '@nuxtjs/i18n', "@nuxtjs/tailwindcss"],
|
||||
"/": { redirect: "/home" },
|
||||
"/zh_tw": { redirect: "/zh_tw/home" },
|
||||
},
|
||||
css: ["~/styles/main.css"],
|
||||
modules: [
|
||||
"@nuxt/image",
|
||||
"@nuxtjs/robots",
|
||||
"@nuxtjs/seo",
|
||||
"@nuxtjs/i18n",
|
||||
"@nuxtjs/tailwindcss",
|
||||
],
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
vueI18n: './i18n.config.ts',
|
||||
defaultLocale: "en",
|
||||
vueI18n: "./i18n.config.ts",
|
||||
locales: [
|
||||
{ code: 'en', name: 'English', file: 'en.json' },
|
||||
{ code: 'zh_tw', name: 'Chinese Tradional', file: 'zh-tw.json' },
|
||||
]
|
||||
{ code: "en", name: "English", file: "en.json" },
|
||||
{ code: "zh_tw", name: "Chinese Tradional", file: "zh-tw.json" },
|
||||
],
|
||||
},
|
||||
site: {
|
||||
url: "https://news.yuanhau.com",
|
||||
@ -28,14 +34,17 @@ export default defineNuxtConfig({
|
||||
{ charset: "utf-8" },
|
||||
{ name: "viewport", content: "width=device-width, initial-scale=1" },
|
||||
{ name: "og:author", content: "@hpware on GitHub" },
|
||||
{ name: "og:author:email", content: "public+newscompareauthor@yuanhau.com" },
|
||||
]
|
||||
}
|
||||
{
|
||||
name: "og:author:email",
|
||||
content: "public+newscompareauthor@yuanhau.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
postcss: {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},// Add your content paths here
|
||||
}, // Add your content paths here
|
||||
},
|
||||
})
|
||||
});
|
||||
|
@ -19,6 +19,7 @@
|
||||
"@nuxtjs/tailwindcss": "6.14.0",
|
||||
"@tailwindcss/vite": "^4.1.5",
|
||||
"@uploadthing/nuxt": "^7.1.7",
|
||||
"animate.css": "^4.1.1",
|
||||
"bootstrap-icons": "^1.12.1",
|
||||
"gsap": "^3.13.0",
|
||||
"nuxt": "^3.17.2",
|
||||
|
@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-center">
|
||||
嗨!
|
||||
</h1>
|
||||
<h1 class="text-3xl font-bold text-center">嗨!</h1>
|
||||
</div>
|
||||
</template>
|
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { gsap } from 'gsap';
|
||||
import { ScrambleTextPlugin } from 'gsap/dist/ScrambleTextPlugin';
|
||||
gsap.registerPlugin(ScrambleTextPlugin)
|
||||
import { gsap } from "gsap";
|
||||
import { ScrambleTextPlugin } from "gsap/dist/ScrambleTextPlugin";
|
||||
gsap.registerPlugin(ScrambleTextPlugin);
|
||||
const loading = ref(true);
|
||||
const route = useRoute();
|
||||
const slug = route.params.slug;
|
||||
@ -11,7 +11,11 @@ definePageMeta({
|
||||
layout: "newsorg",
|
||||
});
|
||||
|
||||
const { data: fetchNewsOrgInfo, pending, error } = useFetch("/api/getData/fetchNewsOrgInfo", {
|
||||
const {
|
||||
data: fetchNewsOrgInfo,
|
||||
pending,
|
||||
error,
|
||||
} = useFetch("/api/getData/fetchNewsOrgInfo", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@ -35,7 +39,7 @@ onMounted(() => {
|
||||
gsap.to(orgNameAnimation.value, {
|
||||
duration: 1,
|
||||
scrambleText: fetchNewsOrgInfo.value?.title,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Import Icons
|
||||
@ -44,16 +48,32 @@ import { GlobeAltIcon } from "@heroicons/vue/24/outline";
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-center align-center justify-center">
|
||||
<div class="flex flex-row bg-[#AAACAAFF] rounded-3xl p-3 gap-3 m-3">
|
||||
<NuxtImg :src="fetchNewsOrgInfo?.logoUrl" class="w-48 h-48 rounded-[10px]"/>
|
||||
<div
|
||||
class="flex flex-row bg-[#AAACAAFF] rounded-3xl p-3 gap-3 m-3 scale-5"
|
||||
>
|
||||
<NuxtImg
|
||||
:src="fetchNewsOrgInfo?.logoUrl"
|
||||
class="w-48 h-48 rounded-[10px]"
|
||||
/>
|
||||
<div class="flex flex-col gap-3 text-left">
|
||||
<h1 class="text-4xl font-bold m-3 text-left">{{ fetchNewsOrgInfo?.title }}</h1>
|
||||
<span class="text-ms m-1 mt-5 text-left text-wrap">{{ fetchNewsOrgInfo?.description }}</span>
|
||||
<h1 class="text-4xl font-bold m-3 text-left">
|
||||
{{ fetchNewsOrgInfo?.title }}
|
||||
</h1>
|
||||
<span class="text-ms m-1 mt-5 text-left text-wrap">{{
|
||||
fetchNewsOrgInfo?.description
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gap-[3px] flex flex-row text-center align-center justify-center">
|
||||
<a :href="fetchNewsOrgInfo?.website" target="_blank" class="text-blue-200 hover:text-blue-300 transiton-all duration-100 flex flex-row"><GlobeAltIcon class="w-6 h-6" />網站</a>
|
||||
<div
|
||||
class="gap-[3px] flex flex-row text-center align-center justify-center"
|
||||
>
|
||||
<a
|
||||
:href="fetchNewsOrgInfo?.website"
|
||||
target="_blank"
|
||||
class="text-blue-200 hover:text-blue-300 transiton-all duration-100 flex flex-row"
|
||||
><GlobeAltIcon class="w-6 h-6" />網站</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
export default defineEventHandler(async(event) => {
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
return {
|
||||
body: body,
|
||||
@ -7,8 +7,7 @@ export default defineEventHandler(async(event) => {
|
||||
website: "https://www.taisounds.com.tw",
|
||||
description: "wah wah wah wah wah wah I dont fucking care",
|
||||
facebook: "https://www.facebook.com/taisounds",
|
||||
logoUrl: "https://cdn.discordapp.com/avatars/918723093646684180/4eecc27ac05ee8a701fa167808610c7a.jpg",
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
logoUrl:
|
||||
"https://cdn.discordapp.com/avatars/918723093646684180/4eecc27ac05ee8a701fa167808610c7a.jpg",
|
||||
};
|
||||
});
|
||||
|
@ -2,5 +2,9 @@ import s3 from "~/server/components/s3";
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const slug = getRouterParam(event, "slug");
|
||||
return sendRedirect(event, `${process.env.S3_ENDPOINT}/${process.env.S3_BUCKETNAME}/${slug}`, 302);
|
||||
})
|
||||
return sendRedirect(
|
||||
event,
|
||||
`${process.env.S3_ENDPOINT}/${process.env.S3_BUCKETNAME}/${slug}`,
|
||||
302,
|
||||
);
|
||||
});
|
||||
|
@ -1,3 +1 @@
|
||||
export default defineEventHandler(async () => {
|
||||
|
||||
});
|
||||
export default defineEventHandler(async () => {});
|
||||
|
@ -9,4 +9,4 @@
|
||||
body {
|
||||
@apply bg-black m-0 p-0 min-h-screen text-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,15 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
|
||||
}
|
||||
content: [],
|
||||
theme: {
|
||||
extend: {
|
||||
backgroundColor: {
|
||||
page: "#000000",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
corePlugins: {
|
||||
preflight: true,
|
||||
},
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user