From 44a7e48c60f6487d30d473cbb3ec2016e97a3d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E4=B8=9C=E4=BA=AE?= Date: Thu, 23 Jul 2026 16:03:29 +0800 Subject: [PATCH] stage --- .gitignore | 1 + app.db | Bin 24576 -> 24576 bytes frontend/index.html | 6 +- frontend/public/images/0012.jpg | Bin 3159 -> 0 bytes frontend/public/images/1784707678705.jpg | Bin 15070 -> 0 bytes frontend/src/components/History.tsx | 22 ++++++-- frontend/src/components/ImagePreview.tsx | 27 +++++++++ frontend/src/components/Main.tsx | 51 +++++++++++++++-- frontend/src/components/Navbar.tsx | 24 ++++++-- frontend/src/pages/App.tsx | 2 +- frontend/src/styles/base.sass | 69 ++++++++++++++++++----- frontend/src/styles/history.sass | 33 +++++++++-- 12 files changed, 194 insertions(+), 41 deletions(-) delete mode 100644 frontend/public/images/0012.jpg delete mode 100644 frontend/public/images/1784707678705.jpg create mode 100644 frontend/src/components/ImagePreview.tsx diff --git a/.gitignore b/.gitignore index 67dd9e4..8b56209 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ nn/models/*.pt build/bin frontend/node_modules frontend/dist +frontend/public diff --git a/app.db b/app.db index 1d79e280190a8013b53b469da5924d0836f85068..14325bda35ba0935506e919b9d5325614089c157 100644 GIT binary patch delta 352 zcmYk%ze)o^5C-t9D0Vj&HF{wzt?zDk_RnnX3xt$bS_xNZ-XKA+6VcYvE~Q+rQ84OD z2x27`Vr}CRmfY1pzHjE6%*13Su29(P-F;#24lfJQuYZbOnyrKBz$eUM3Kwt+Lokpf zf605@O`no6Zme|*u__&F$A-uomU%TgUa5|z_t&tzz%X7jCyux$sg+F*(1%UJE602y;w6 h9^h6B%P>_+&a1t}(uWV+Y?PhX#L~px`uBE_{sSo-R!#r_ delta 258 zcmZoTz}Rqrae_3X%0wAwMwN{Tefo?Xo8Rk;3J5U>Ffi~R-;_ zp1)q2os~hKk;Ty5!oV!Z diff --git a/frontend/index.html b/frontend/index.html index aba2420..e6ca92f 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,9 +3,9 @@ - + dissertation - -->
diff --git a/frontend/public/images/0012.jpg b/frontend/public/images/0012.jpg deleted file mode 100644 index 5c16524207b341a6f56347096cc240c0dec22760..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3159 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 X_Pwmq6rsbxu3@p6MqBeX*6_aopho9Q diff --git a/frontend/public/images/1784707678705.jpg b/frontend/public/images/1784707678705.jpg deleted file mode 100644 index 1f51ca52e4f1da74a52377fa947375c8e1987881..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15070 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 { const date = new Date(timestamp * 1000) return date.toLocaleString('zh-CN', { @@ -104,7 +104,7 @@ const History = () => { {historyList.map((item: HistoryItem) =>
- +
@@ -122,9 +122,19 @@ const History = () => {
) } -
- -
+ {historyList.length ? +
+ +
: null + } + {!historyList.length ? +
+ + + +

暂无记录

+
: null + }

确定要删除当前记录?

diff --git a/frontend/src/components/ImagePreview.tsx b/frontend/src/components/ImagePreview.tsx new file mode 100644 index 0000000..2409b4a --- /dev/null +++ b/frontend/src/components/ImagePreview.tsx @@ -0,0 +1,27 @@ +import { useState, useEffect } from 'preact/hooks' + +interface Props { + filename: string + class?: string + id?: string +} + +const ImagePreview = ({ filename, ...props }: Props) => { + const [src, setSrc] = useState('') + + useEffect(() => { + const loadImage = async () => { + const result = await (window as any).go.main.App.GetImage(filename) + if (result.code === 0) { + setSrc(result.data) + } + } + loadImage() + }, [filename]) + + if (!src) return
+ + return +} + +export default ImagePreview diff --git a/frontend/src/components/Main.tsx b/frontend/src/components/Main.tsx index 83f1635..deff108 100644 --- a/frontend/src/components/Main.tsx +++ b/frontend/src/components/Main.tsx @@ -1,7 +1,7 @@ import { useState, useRef } from 'preact/hooks' -import { message } from '../utils/toast' import type { DetectResult } from '../preact' - +import ImagePreview from './ImagePreview' +import { message } from '../utils/toast' const Main = () => { const fileInputRef = useRef(null) @@ -11,14 +11,53 @@ const Main = () => { const handleUploadClick = () => fileInputRef.current?.click() + function loadImage(file: File): Promise { + return new Promise((resolve) => { + const img = new Image() + img.onload = () => resolve(img) + img.src = URL.createObjectURL(file) + }) + } + + const resizeImage = async(file: File, maxWidth = 224): Promise => { + const img = await loadImage(file) + if (img.width <= maxWidth) { + return file + } + + const canvas = document.createElement('canvas') + const ratio = maxWidth / img.width + canvas.width = maxWidth + canvas.height = Math.round(img.height * ratio) + + const ctx = canvas.getContext('2d') as CanvasRenderingContext2D + ctx.imageSmoothingEnabled = true + ctx.imageSmoothingQuality = 'high' + ctx.drawImage(img, 0, 0, canvas.width, canvas.height) + + return new Promise((resolve) => { + canvas.toBlob((blob: Blob | null) => { + if (!blob) { + resolve(file) + return + } + resolve(new File([blob], file.name, { type: file.type })) + }, file.type, 0.9) + }) + } + const handleFileChange = (e: Event) => { console.log('handleFileChange') const target = e.target as HTMLInputElement const file = target.files?.[0] if (file) { + console.log('文件大小:', file.size / 1024) + const reader = new FileReader() reader.onload = async function() { - const arrayBuffer = reader.result as ArrayBuffer + const processedFile = await resizeImage(file, 224) + + const arrayBuffer = await processedFile.arrayBuffer() const uint8Array = new Uint8Array(arrayBuffer) const result = await (window as any).go.main.App.UploadImage( @@ -94,7 +133,7 @@ const Main = () => { > {fileSrc.length > 0 && step == 1 ?
- + @@ -147,13 +186,13 @@ const Main = () => {
- +

完成!

- +

{detectResult?.name}

diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx index 3eac2b3..e53a664 100644 --- a/frontend/src/components/Navbar.tsx +++ b/frontend/src/components/Navbar.tsx @@ -1,23 +1,35 @@ -export const Navbar = () => { +const Navbar = () => { const svgPath = "M12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-4.5 4c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm9 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-9.5 3.5c-1.38 0-2.5 1.12-2.5 2.5s1.12 2.5 2.5 2.5 2.5-1.12 2.5-2.5-1.12-2.5-2.5-2.5zm11 0c-1.38 0-2.5 1.12-2.5 2.5s1.12 2.5 2.5 2.5 2.5-1.12 2.5-2.5-1.12-2.5-2.5-2.5zM12 18c-2.21 0-4 1.79-4 4h8c0-2.21-1.79-4-4-4z" const handleClick = () => window.open('https://git.leonstack.com/owner/Collage-Images', '_blank') + const handleNavColor = (e: Event) => { + const current = e.currentTarget as HTMLElement + const parent = current.parentElement + if (parent) { + parent.querySelectorAll('a').forEach(a => a.classList.remove('active')) + } + + current.classList.add('active') + } + return ( -