add bun backend and add upload bitstream component

This commit is contained in:
SikongJueluo 2025-03-18 17:28:21 +08:00
parent 4980b84da6
commit d766e2ae6a
No known key found for this signature in database
13 changed files with 178 additions and 17 deletions

View File

@ -13,6 +13,7 @@
"devDependencies": {
"@tailwindcss/postcss": "^4.0.12",
"@tsconfig/node22": "^22.0.0",
"@types/bun": "^1.2.5",
"@types/node": "^22.13.4",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
@ -231,10 +232,14 @@
"@tsconfig/node22": ["@tsconfig/node22@22.0.0", "", {}, "sha512-twLQ77zevtxobBOD4ToAtVmuYrpeYUh3qh+TEp+08IWhpsrIflVHqQ1F1CiPxQGL7doCdBIOOCF+1Tm833faNg=="],
"@types/bun": ["@types/bun@1.2.5", "", { "dependencies": { "bun-types": "1.2.5" } }, "sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg=="],
"@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
"@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="],
"@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
"@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.1", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ=="],
"@vitejs/plugin-vue-jsx": ["@vitejs/plugin-vue-jsx@4.1.1", "", { "dependencies": { "@babel/core": "^7.26.0", "@babel/plugin-transform-typescript": "^7.25.9", "@vue/babel-plugin-jsx": "^1.2.5" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.0.0" } }, "sha512-uMJqv/7u1zz/9NbWAD3XdjaY20tKTf17XVfQ9zq4wY1BjsB/PjpJPMe2xiG39QpP4ZdhYNhm4Hvo66uJrykNLA=="],
@ -299,6 +304,8 @@
"bun-plugin-tailwind": ["bun-plugin-tailwind@0.0.15", "", { "peerDependencies": { "typescript": "^5.0.0" } }, "sha512-qtAXMNGG4R0UGGI8zWrqm2B7BdXqx48vunJXBPzfDOHPA5WkRUZdTSbE7TFwO4jLhYqSE23YMWsM9NhE6ovobw=="],
"bun-types": ["bun-types@1.2.5", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-3oO6LVGGRRKI4kHINx5PIdIgnLRb7l/SprhzqXapmoYkFl5m4j6EvALvbDVuuBFaamB46Ap6HCUxIXNLCGy+tg=="],
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
"caniuse-lite": ["caniuse-lite@1.0.30001702", "", {}, "sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA=="],

View File

@ -3,12 +3,14 @@
"version": "0.0.0",
"private": true,
"type": "module",
"main": "./server/index.ts",
"scripts": {
"dev": "bunx --bun vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "bunx --bun vite preview",
"build-only": "bunx --bun vite build",
"type-check": "bunx --bun vue-tsc --build"
"type-check": "bunx --bun vue-tsc --build",
"server": "bun run ./server/index.ts"
},
"dependencies": {
"log-symbols": "^7.0.0",
@ -20,6 +22,7 @@
"devDependencies": {
"@tailwindcss/postcss": "^4.0.12",
"@tsconfig/node22": "^22.0.0",
"@types/bun": "^1.2.5",
"@types/node": "^22.13.4",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",

0
server/DataBase.ts Normal file
View File

39
server/index.ts Normal file
View File

@ -0,0 +1,39 @@
import { serve } from "bun";
serve({
port: 3001,
// hostname: "fpga.swordlost.com",
routes: {
// Static routes
"/api/status": new Response("OK"),
// Dynamic routes
"/users/:id": req => {
return new Response(`Hello User ${req.params.id}!`);
},
// Per-HTTP method handlers
"/api/posts": {
GET: () => new Response("List posts"),
POST: async req => {
const body = await req.json();
if (body !== null) {
return Response.json({ created: true, ...body });
} else {
return Response.json({})
}
},
},
// Wildcard route for all routes that start with "/api/" and aren't otherwise matched
"/api/*": Response.json({ message: "Not found" }, { status: 404 }),
// Serve a file by buffering it in memory
// "/favicon.ico": new Response(await Bun.file("../public/favicon.icon").bytes(), {
// headers: {
// "Content-Type": "image/x-icon",
// },
// }),
}
});

View File

@ -1,8 +1,15 @@
<template>
<div :class="themeSidebar">
<div class="card-body flex">
<div :class="[
'card-dash',
'sidebar-base',
'transition-all',
'duration-500',
'ease-in-out',
isClose ? 'sidebar-close' : 'sidebar-open',
]">
<div class="card-body flex transition-all duration-500 ease-in-out">
<!-- Avatar and Name -->
<div class="flex items-center">
<div :class="['flex', 'items-center', isClose ? 'flex-col' : '']">
<!-- Img -->
<div class="avatar h-10">
<div class="rounded-full">
@ -15,7 +22,7 @@
</div>
<!-- Toggle Button -->
<button class="btn btn-square rounded-lg p-2" @click="toggleSidebar">
<button class="btn btn-square rounded-lg p-2 m-3" @click="toggleSidebar">
<img src="../assets/left.svg" alt="Menu Button" class="opacity-50">
</button>
</div>
@ -51,7 +58,7 @@
<script setup lang="ts">
import iconMenu from "../assets/menu.svg"
import { useThemeStore } from "@/stores/theme";
import { ref } from "vue";
import { computed, ref } from "vue";
import ThemeControlButton from "./ThemeControlButton.vue";
import ThemeControlToggle from "./ThemeControlToggle.vue";
@ -65,7 +72,16 @@ const items = [
{ id: 4, icon: iconMenu, msg: "btn4" },
]
const themeSidebar = ref("card-dash sidebar-base sidebar-open")
const themeSidebar = computed(() => {
return [
"card-dash",
"sidebar-base",
"transition",
"duration-300",
"ease-in-out",
isClose.value ? "sidebar-close" : "sidebar-open",
]
})
function closeSidebar() {
isClose.value = true;
@ -80,11 +96,11 @@ function openSidebar() {
function toggleSidebar() {
if (isClose.value) {
openSidebar()
themeSidebar.value = "card-dash sidebar-base sidebar-open"
// themeSidebar.value = "card-dash sidebar-base sidebar-open"
}
else {
closeSidebar()
themeSidebar.value = "card-dash sidebar-base sidebar-close"
// themeSidebar.value = "card-dash sidebar-base sidebar-close"
}
}

View File

@ -0,0 +1,52 @@
<template>
<div class="card card-dash shadow-xl w-90 h-60">
<div class="card-body flex">
<!-- Title -->
<h1 class="card-title place-self-center font-bold text-2xl">上传比特流文件</h1>
<!-- Input File -->
<fieldset class="fieldset w-full">
<legend class="fieldset-legend text-sm">选择或拖拽上传文件</legend>
<input type="file" class="file-input" @change="handleFileChange" />
<label class="fieldset-label">Max size 2MB</label>
</fieldset>
<!-- Upload Button -->
<div class="card-actions">
<button @click="uploadBitStream" class="btn btn-primary grow">上传</button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
var bitstream = null;
function handleFileChange(event: Event): void {
const target = event.target as HTMLInputElement;
const file = target.files?.[0]; //
if (!file) {
console.error('未选择文件');
return;
}
bitstream = file;
console.log(bitstream);
}
function uploadBitStream() {
}
function checkFileType(file: File) {
}
</script>
<style scoped lang="postcss">
@import "../assets/main.css";
</style>

View File

@ -8,3 +8,5 @@ import router from './router'
const app = createApp(App).use(router).use(createPinia()).mount('#app')
console.log()

View File

@ -1,13 +1,13 @@
import { createMemoryHistory, createRouter } from 'vue-router'
import LoginView from "@/views/LoginView.vue"
import UserView from '@/views/UserView.vue'
import TestSVG from '@/views/TestSVG.vue'
import TestView from '@/views/TestView.vue'
const routes = [
{ path: "/", redirect: "/user" },
{ path: "/login", name: "Login", component: LoginView },
{ path: "/user", name: "User", component: UserView },
{ path: "/test", name: "Test", component: TestSVG },
{ path: "/test", name: "Test", component: TestView },
]
const router = createRouter({

View File

@ -1,12 +1,18 @@
<template>
<main>
<div class="w-full h-full">
<header>
</header>
<main class="relative">
<div class="fixed left-0 top-0 z-50">
<Sidebar />
</div>
<div class="w-screen h-screen flex items-center justify-center">
<UploadCard />
</div>
</main>
</template>
<script setup lang="ts">
import UploadCard from '@/components/UploadCard.vue';
import Sidebar from '../components/Sidebar.vue'
</script>

View File

@ -1,12 +1,19 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"include": [
"env.d.ts",
"src/**/*",
"src/**/*.vue"
],
"exclude": [
"src/**/__tests__/*"
],
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"paths": {
"@/*": ["./src/*"]
"@/*": [
"./src/*"
]
}
}
}

26
tsconfig.bun.json Normal file
View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
// Enable latest features
"lib": [
"ESNext"
],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
// Some stricter flags
"noUnusedLocals": true,
"noUnusedParameters": true,
"noPropertyAccessFromIndexSignature": true
}
}

View File

@ -6,6 +6,9 @@
},
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.bun.json"
}
]
}