Clean the code via prettier.

This commit is contained in:
吳元皓 2025-05-12 21:05:45 +08:00
parent 57aa0aba18
commit eaa9b15b2d
10 changed files with 177 additions and 165 deletions

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useThrottleFn } from '@vueuse/core' import { useThrottleFn } from "@vueuse/core";
const props = defineProps<{ const props = defineProps<{
title: string; title: string;
@ -10,44 +10,52 @@ const props = defineProps<{
}>(); }>();
const emit = defineEmits(["close", "min", "maximize", "restore"]); const emit = defineEmits(["close", "min", "maximize", "restore"]);
const title = computed(() => props.title || 'Draggable Window'); const title = computed(() => props.title || "Draggable Window");
const isDragging = ref(false); const isDragging = ref(false);
const position = ref({ const position = ref({
x: props.initialX || Math.floor(window.innerWidth / 2 - (parseInt(props.width || '400') / 2)), x:
y: props.initialY || Math.floor(window.innerHeight / 2 - (parseInt(props.height || '300') / 2)), props.initialX ||
Math.floor(window.innerWidth / 2 - parseInt(props.width || "400") / 2),
y:
props.initialY ||
Math.floor(window.innerHeight / 2 - parseInt(props.height || "300") / 2),
}); });
const offset = ref({ x: 0, y: 0 }); const offset = ref({ x: 0, y: 0 });
const doDrag = useThrottleFn((e: MouseEvent) => { const doDrag = useThrottleFn((e: MouseEvent) => {
if (!isDragging.value) return if (!isDragging.value) return;
requestAnimationFrame(() => { requestAnimationFrame(() => {
position.value = { position.value = {
x: Math.max(0, Math.min(window.innerWidth - 400, e.clientX - offset.value.x)), x: Math.max(
y: Math.max(0, Math.min(window.innerHeight - 300, e.clientY - offset.value.y)) 0,
} Math.min(window.innerWidth - 400, e.clientX - offset.value.x),
}) ),
y: Math.max(
0,
Math.min(window.innerHeight - 300, e.clientY - offset.value.y),
),
};
});
}, 16); }, 16);
const startDrag = (e: MouseEvent) => { const startDrag = (e: MouseEvent) => {
isDragging.value = true isDragging.value = true;
offset.value = { offset.value = {
x: e.clientX - position.value.x, x: e.clientX - position.value.x,
y: e.clientY - position.value.y y: e.clientY - position.value.y,
} };
document.addEventListener('mousemove', doDrag) document.addEventListener("mousemove", doDrag);
document.addEventListener('mouseup', stopDrag) document.addEventListener("mouseup", stopDrag);
} };
const stopDrag = () => { const stopDrag = () => {
isDragging.value = false isDragging.value = false;
document.removeEventListener('mousemove', doDrag) document.removeEventListener("mousemove", doDrag);
document.removeEventListener('mouseup', stopDrag) document.removeEventListener("mouseup", stopDrag);
} };
</script> </script>
<template> <template>

View File

@ -11,7 +11,6 @@ try {
} catch (error) { } catch (error) {
console.error("Error:", error); console.error("Error:", error);
} }
</script> </script>
<template> <template>
<div <div

View File

@ -3,36 +3,36 @@ import sha512 from "crypto-js/sha512";
const userAccount = ref(""); const userAccount = ref("");
const userPassword = ref(""); const userPassword = ref("");
const submitUserPassword = async () => { const submitUserPassword = async () => {
// Encrypt password during transit // Encrypt password during transit
const password = sha512(userPassword.value).toString(); const password = sha512(userPassword.value).toString();
// Send data. // Send data.
const sendData = await fetch("/api/user/login", { const sendData = await fetch("/api/user/login", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
body: JSON.stringify({ body: JSON.stringify({
username: userAccount.value, username: userAccount.value,
password: password, password: password,
}), }),
}) });
const res = await sendData.json(); const res = await sendData.json();
if (res.status === "ok") { if (res.status === "ok") {
// Store the token in local storage // Store the token in local storage
localStorage.setItem("token", res.token); localStorage.setItem("token", res.token);
// Redirect to the home page // Redirect to the home page
window.location.href = "/"; window.location.href = "/";
success.value = true; success.value = true;
} else { } else {
alert("Login failed"); alert("Login failed");
error.value = true; error.value = true;
} }
// Clear the input fields // Clear the input fields
userAccount.value = ""; userAccount.value = "";
userPassword.value = ""; userPassword.value = "";
} };
</script> </script>
<template> <template>
<div class="flex flex-col items-center justify-center h-full"> <div class="flex flex-col items-center justify-center h-full">

View File

@ -1,22 +1,26 @@
<script setup lang="ts"> <script setup lang="ts">
const { t, locale } = useI18n(); const { t, locale } = useI18n();
const { data: source, pending, error } = await useFetch("/api/getData/fetchSources", { const {
method: "POST", data: source,
headers: { pending,
"Content-Type": "application/json", error,
}, } = await useFetch("/api/getData/fetchSources", {
body: { method: "POST",
lang: locale, headers: {
}, "Content-Type": "application/json",
},
body: {
lang: locale,
},
}); });
</script> </script>
<template> <template>
<div > <div>
<div v-for="item in source?.data" :key="item.id"> <div v-for="item in source?.data" :key="item.id">
<h1>{{ item.title }}</h1> <h1>{{ item.title }}</h1>
<span>{{ item.description }}</span> <span>{{ item.description }}</span>
<a :href="item.url">{{ item.url }}</a> <a :href="item.url">{{ item.url }}</a>
</div>
</div> </div>
</div>
</template> </template>

View File

@ -18,7 +18,7 @@
"startusing": "開始使用!", "startusing": "開始使用!",
"learnmore": "了解更多", "learnmore": "了解更多",
"whydes": "台灣的新聞是要痲是來自中國控制的媒體,或是來自只想獲得點閱的記者。", "whydes": "台灣的新聞是要痲是來自中國控制的媒體,或是來自只想獲得點閱的記者。",
"howdes":" 我們使用使用 Python 寫的網頁爬蟲來搜尋最新的新聞並將其存入Postgres資料庫中。" "howdes": " 我們使用使用 Python 寫的網頁爬蟲來搜尋最新的新聞並將其存入Postgres資料庫中。"
}, },
"dailybriefing": "今日報導", "dailybriefing": "今日報導",
"Welcome": "歡迎", "Welcome": "歡迎",

View File

@ -135,7 +135,7 @@ onMounted(async () => {
if (openApp.value) { if (openApp.value) {
openWindow(openApp.value); openWindow(openApp.value);
} }
}) });
const associAppWindow = [ const associAppWindow = [
{ {
@ -146,24 +146,31 @@ const associAppWindow = [
width: "700px", width: "700px",
height: "500px", height: "500px",
}, },
{ name: "login", id: "2", title: t("app.login") , component: LoginWindow }, { name: "login", id: "2", title: t("app.login"), component: LoginWindow },
{ name: "sources", id: "3", title: t("app.sources"), component: SourcesWindow } {
name: "sources",
id: "3",
title: t("app.sources"),
component: SourcesWindow,
},
]; ];
const currentOpenAppId = ref(0); const currentOpenAppId = ref(0);
const findAndOpenWindow = (windowName: string) => { const findAndOpenWindow = (windowName: string) => {
const app = associAppWindow.find((app) => app.name === windowName) const app = associAppWindow.find((app) => app.name === windowName);
// Prevent dual logins // Prevent dual logins
if (windowName === "login" && if (
activeWindows.value.some((window) => window.name === "login")) { windowName === "login" &&
return activeWindows.value.some((window) => window.name === "login")
) {
return;
} }
if (app) { if (app) {
// Use shallowRef for better performance with components // Use shallowRef for better performance with components
const windowComponent = shallowRef(app.component) const windowComponent = shallowRef(app.component);
activeWindows.value.push({ activeWindows.value.push({
id: currentOpenAppId.value, id: currentOpenAppId.value,
@ -172,10 +179,10 @@ const findAndOpenWindow = (windowName: string) => {
title: app.title, title: app.title,
width: app.width || "400px", width: app.width || "400px",
height: app.height || "300px", height: app.height || "300px",
}) });
currentOpenAppId.value++; currentOpenAppId.value++;
} }
} };
const closeWindow = (windowId: string) => { const closeWindow = (windowId: string) => {
activeWindows.value = activeWindows.value.filter( activeWindows.value = activeWindows.value.filter(
@ -196,7 +203,7 @@ const topWindow = (windowId: string) => {
useSeoMeta({ useSeoMeta({
title: "hi" + " - Desktop", title: "hi" + " - Desktop",
}) });
</script> </script>
<template> <template>
<div <div
@ -263,27 +270,27 @@ useSeoMeta({
class="flex flex-col justify-center align-center text-center absolute w-full h-screen inset-x-0 inset-y-0 z-[-10]" class="flex flex-col justify-center align-center text-center absolute w-full h-screen inset-x-0 inset-y-0 z-[-10]"
id="desktop" id="desktop"
></div> ></div>
<Transition> <Transition>
<div> <div>
<DraggableWindow <DraggableWindow
v-for="window in activeWindows" v-for="window in activeWindows"
:key="window.id" :key="window.id"
:title="window.title" :title="window.title"
@close="closeWindow(window.id)" @close="closeWindow(window.id)"
@min="unMinWindow(window.id)" @min="unMinWindow(window.id)"
:width="window.width" :width="window.width"
:height="window.height" :height="window.height"
@clicked="topWindow(window.id)" @clicked="topWindow(window.id)"
> >
<Suspense> <Suspense>
<Component <Component
:is="window.component" :is="window.component"
@error="console.error('Error:', $event)" @error="console.error('Error:', $event)"
/> />
</Suspense> </Suspense>
</DraggableWindow> </DraggableWindow>
</div> </div>
</Transition> </Transition>
<!--Footer--> <!--Footer-->
<div <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" 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"

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="justify-center align-center text-center"> <div class="justify-center align-center text-center">
<span class="text-6xl text-bold">目前沒有手機版本</span> <span class="text-6xl text-bold">目前沒有手機版本</span>
<span class="text-xl">請使用電腦版</span> <span class="text-xl">請使用電腦版</span>
</div> </div>
</template> </template>

View File

@ -78,18 +78,14 @@ onMounted(() => {
> >
<h1 class="text-8xl mt-0">🤔</h1> <h1 class="text-8xl mt-0">🤔</h1>
<h2 class="text-xl font-bold">Why?</h2> <h2 class="text-xl font-bold">Why?</h2>
<span class="text-sm" <span class="text-sm">{{ t("home.whydes") }}</span>
>{{ t("home.whydes")}}</span
>
</div> </div>
<div <div
class="flex flex-col justify-center items-center align-middle bg-[#C9C9C9]/60 rounded-xl shadow-lg p-5 m-5 w-[300px] h-[200px]" class="flex flex-col justify-center items-center align-middle bg-[#C9C9C9]/60 rounded-xl shadow-lg p-5 m-5 w-[300px] h-[200px]"
> >
<h1 class="text-8xl mt-0">🧐</h1> <h1 class="text-8xl mt-0">🧐</h1>
<h2 class="text-xl font-bold">How?</h2> <h2 class="text-xl font-bold">How?</h2>
<span class="text-sm" <span class="text-sm">{{ t("home.howdes") }}</span>
>{{ t("home.howdes")}}</span
>
</div> </div>
</div> </div>
<br /> <br />

View File

@ -1,25 +1,25 @@
import sql from "~/server/components/postgres"; import sql from "~/server/components/postgres";
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
const body = await readBody(event); const body = await readBody(event);
const query = getQuery(event); const query = getQuery(event);
/*const sources = await sql`SELECT * FROM sources`; /*const sources = await sql`SELECT * FROM sources`;
return sources;*/ return sources;*/
// Fake data // Fake data
return { return {
status: "ok", status: "ok",
data: [ data: [
{ {
id: 1, id: 1,
title: "Source 1", title: "Source 1",
url: "https://source1.com", url: "https://source1.com",
description: "Description for Source 1", description: "Description for Source 1",
}, },
{ {
id: 2, id: 2,
title: "Source 2", title: "Source 2",
url: "https://source2.com", url: "https://source2.com",
description: "Description for Source 2", description: "Description for Source 2",
} },
] ],
} };
}) });

View File

@ -1,36 +1,34 @@
import sql from "~/server/components/postgres"; import sql from "~/server/components/postgres";
import argon2 from "argon2"; import argon2 from "argon2";
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
const salt = process.env.PASSWORD_HASH_SALT; const salt = process.env.PASSWORD_HASH_SALT;
if (!salt) { if (!salt) {
throw createError({ throw createError({
statusCode: 500, statusCode: 500,
message: 'Internal server error' message: "Internal server error",
}); });
} }
const body = await readBody(event); const body = await readBody(event);
const { username, password } = body; const { username, password } = body;
if (!username || !password) { if (!username || !password) {
throw createError({ throw createError({
statusCode: 400, statusCode: 400,
message: 'Username and password are required' message: "Username and password are required",
}); });
} }
const USERNAME_PATTERN = /^[a-zA-Z0-9_]{3,20}$/; const USERNAME_PATTERN = /^[a-zA-Z0-9_]{3,20}$/;
if (!USERNAME_PATTERN.test(username)) { if (!USERNAME_PATTERN.test(username)) {
throw createError({ throw createError({
statusCode: 400, statusCode: 400,
message: 'Invalid username.' message: "Invalid username.",
}); });
} }
// Server side hashing // Server side hashing
const hashedPassword = await argon2.hash(salt, password); const hashedPassword = await argon2.hash(salt, password);
// Check if user exists, if not, create a user // Check if user exists, if not, create a user
try { try {
console.log(username); console.log(username);
console.log(hashedPassword); console.log(hashedPassword);
} catch (e) { } catch (e) {}
});
}
})