init
This commit is contained in:
parent
99907e5051
commit
dc71938bd8
7 changed files with 123 additions and 99 deletions
|
@ -34,3 +34,7 @@ You can check out [the Next.js GitHub repository](https://github.com/vercel/next
|
||||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||||
|
|
||||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||||
|
|
||||||
|
|
||||||
|
# Structure
|
||||||
|
Store on local machine and use a middleware to process (compress) the file and facilitate storage.
|
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
@ -9,9 +9,10 @@
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"bun-types": "^1.2.9",
|
||||||
|
"next": "15.3.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0"
|
||||||
"next": "15.3.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5",
|
"typescript": "^5",
|
||||||
|
|
15
services/docker-compose.yml
Normal file
15
services/docker-compose.yml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:17.4-alpine3.21
|
||||||
|
restart: always
|
||||||
|
shm_size: 128mb
|
||||||
|
environment:
|
||||||
|
- POSTGRES_PASSWORD=test
|
||||||
|
- POSTGRES_USER=test
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
adminer:
|
||||||
|
image: adminer
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
106
src/app/page.tsx
106
src/app/page.tsx
|
@ -1,103 +1,15 @@
|
||||||
import Image from "next/image";
|
import { retrieve_post } from "@/db";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
|
||||||
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
|
|
||||||
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
|
|
||||||
<Image
|
|
||||||
className="dark:invert"
|
|
||||||
src="/next.svg"
|
|
||||||
alt="Next.js logo"
|
|
||||||
width={180}
|
|
||||||
height={38}
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
<ol className="list-inside list-decimal text-sm/6 text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
|
|
||||||
<li className="mb-2 tracking-[-.01em]">
|
|
||||||
Get started by editing{" "}
|
|
||||||
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-[family-name:var(--font-geist-mono)] font-semibold">
|
|
||||||
src/app/page.tsx
|
|
||||||
</code>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
<li className="tracking-[-.01em]">
|
|
||||||
Save and see your changes instantly.
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
return (
|
||||||
<a
|
<div className="relative min-h-screen px-8 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
|
||||||
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
|
<div className="w-full h-5dvh fixed top-0 left-0">
|
||||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
<h1 className="text-4xl mt-4 ml-3">匿名中工</h1>
|
||||||
target="_blank"
|
</div>
|
||||||
rel="noopener noreferrer"
|
<div className="h-[90dvh] w-[85dvw] absolute left-1/2 top-1/2 mt-5 -translate-1/2">
|
||||||
>
|
|
||||||
<Image
|
</div>
|
||||||
className="dark:invert"
|
|
||||||
src="/vercel.svg"
|
|
||||||
alt="Vercel logomark"
|
|
||||||
width={20}
|
|
||||||
height={20}
|
|
||||||
/>
|
|
||||||
Deploy now
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
|
|
||||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Read our docs
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
|
|
||||||
<a
|
|
||||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
|
||||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
aria-hidden
|
|
||||||
src="/file.svg"
|
|
||||||
alt="File icon"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
Learn
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
|
||||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
aria-hidden
|
|
||||||
src="/window.svg"
|
|
||||||
alt="Window icon"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
Examples
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
|
||||||
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
aria-hidden
|
|
||||||
src="/globe.svg"
|
|
||||||
alt="Globe icon"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
Go to nextjs.org →
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
35
src/app/post.tsx
Normal file
35
src/app/post.tsx
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
import { Suspense } from "react";
|
||||||
|
import Image from "next/image";
|
||||||
|
import { Attachment } from "@/db";
|
||||||
|
|
||||||
|
export default function Post(post_content: string, attachments: Attachment[]) {
|
||||||
|
let images = [];
|
||||||
|
let videos = [];
|
||||||
|
attachments.forEach(attachment => {
|
||||||
|
if (attachment.type.type == "video") {
|
||||||
|
attachment.urls.forEach(url => {
|
||||||
|
videos.push(
|
||||||
|
<Suspense fallback={<p>加載中</p>}>
|
||||||
|
<video controls preload="none" aria-label="Video player">
|
||||||
|
<source src={url} type={attachment.type.toString()} />
|
||||||
|
Your browser does not support the video tag.
|
||||||
|
</video>
|
||||||
|
</Suspense>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}else if (attachment.type.type="image"){
|
||||||
|
attachment.urls.forEach(url => {
|
||||||
|
images.push(<Image src={url} alt="Uploaded" width={300} height={200}></Image>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return (<div className="w-full h-fit">
|
||||||
|
<div>
|
||||||
|
{post_content}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
</div>)
|
||||||
|
}
|
57
src/db.ts
Normal file
57
src/db.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { main } from "bun";
|
||||||
|
import { sql } from "bun";
|
||||||
|
import { MIMEType } from "util"
|
||||||
|
|
||||||
|
export interface Attachment {
|
||||||
|
type: MIMEType;
|
||||||
|
urls: string[];
|
||||||
|
}
|
||||||
|
export interface Post {
|
||||||
|
content: string,
|
||||||
|
hash: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setup_func() {
|
||||||
|
const rows = await sql`
|
||||||
|
CREATE OR REPLACE FUNCTION fetch_post(
|
||||||
|
OUT p_text VARCHAR(1000),
|
||||||
|
OUT p_hash CHAR(32),
|
||||||
|
OUT p_date TIMESTAMP,
|
||||||
|
OUT p_pics INT[]
|
||||||
|
)
|
||||||
|
RETURNS SETOF RECORD AS
|
||||||
|
$$
|
||||||
|
DECLARE
|
||||||
|
post_cursor CURSOR FOR
|
||||||
|
SELECT content, hash, date
|
||||||
|
FROM posts;
|
||||||
|
post_record RECORD;
|
||||||
|
BEGIN
|
||||||
|
-- Open cursor
|
||||||
|
OPEN post_cursor;
|
||||||
|
|
||||||
|
-- Fetch rows and return
|
||||||
|
LOOP
|
||||||
|
FETCH NEXT FROM post_cursor INTO post_record;
|
||||||
|
EXIT WHEN NOT FOUND;
|
||||||
|
|
||||||
|
p_text = post_record.content;
|
||||||
|
p_date = post_record.date;
|
||||||
|
p_hash = post_record.hash;
|
||||||
|
RETURN NEXT;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
-- Close cursor
|
||||||
|
CLOSE post_cursor;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
LANGUAGE PLPGSQL;`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retrieve the latest post with posts table */
|
||||||
|
export async function retrieve_post(offset: Number) {
|
||||||
|
const res = await sql`SELECT * FROM fetch_post();`
|
||||||
|
console.log(res)
|
||||||
|
}
|
||||||
|
setup_func()
|
||||||
|
retrieve_post(0)
|
Loading…
Add table
Reference in a new issue