This commit is contained in:
2026-07-23 16:03:29 +08:00
parent 9f313a54b1
commit 44a7e48c60
12 changed files with 194 additions and 41 deletions
+3 -3
View File
@@ -3,9 +3,9 @@
<head>
<meta charset="UTF-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<script src="https://cdn.tailwindcss.com"></script>
<!-- <script src="https://cdn.tailwindcss.com"></script> -->
<title>dissertation</title>
<script>
<!-- <script>
tailwind.config = {
theme: {
extend: {
@@ -24,7 +24,7 @@
},
},
}
</script>
</script> -->
</head>
<body>
<div id="app"></div>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

+16 -6
View File
@@ -1,10 +1,10 @@
import { useState, useEffect } from 'preact/hooks'
import { message } from '../utils/toast'
import Pagination from './Pagination'
import Modal from './Modal'
import ImagePreview from './ImagePreview'
import { message } from '../utils/toast'
import type { HistoryItem } from '../preact'
const formatDate = (timestamp: number) => {
const date = new Date(timestamp * 1000)
return date.toLocaleString('zh-CN', {
@@ -104,7 +104,7 @@ const History = () => {
{historyList.map((item: HistoryItem) =>
<div key={item.id} class="history-card">
<div class="card-left">
<img src="/images/0012.jpg" alt="" />
<ImagePreview filename={item.img} />
</div>
<div class="card-right">
<div class="right-top">
@@ -122,9 +122,19 @@ const History = () => {
</div>
</div>)
}
<div class="history-pagination">
<Pagination page={page} pagesize={pageSize} total={total} onChange={handlePageChange} />
</div>
{historyList.length ?
<div class="history-pagination">
<Pagination page={page} pagesize={pageSize} total={total} onChange={handlePageChange} />
</div> : null
}
{!historyList.length ?
<div class="history-none">
<svg viewBox="0 0 24 24" fill="none" stroke="#c0c0c0" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z"/>
</svg>
<p></p>
</div> : null
}
</div>
<Modal open={showDelete} title="信息" onClick={handleDeleteOk} onClose={handleDeleteClose}>
<p></p>
+27
View File
@@ -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<string>('')
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 <div {...props} />
return <img src={src} {...props} />
}
export default ImagePreview
+45 -6
View File
@@ -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<HTMLInputElement>(null)
@@ -11,14 +11,53 @@ const Main = () => {
const handleUploadClick = () => fileInputRef.current?.click()
function loadImage(file: File): Promise<HTMLImageElement> {
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<File> => {
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 ?
<div id="previewContent">
<img src={`/images/${fileSrc}`} id="previewImage" />
<ImagePreview filename={fileSrc} id="previewImage" />
<button onClick={handleRemovePhoto}>
</button>
@@ -147,13 +186,13 @@ const Main = () => {
</div>
<div class={`result${step != 3 ? ' hidden' : ''}`}>
<div class="result-complete">
<svg viewBox="0 0 24 24" fill="currentColor">
<svg viewBox="0 0 24 24" fill="#00b740ff">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
<h2></h2>
</div>
<div class="result-main">
<img />
<ImagePreview filename={fileSrc} />
<div class="result-word">
<div>
<h3>{detectResult?.name}</h3>
+18 -6
View File
@@ -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 (
<nav class="app-navbar animate-fade-in">
<nav class="app-navbar">
<div class="navbar-container">
<div class="container-left">
<svg class="icon" viewBox="0 0 24 24" fill="currentColor">
<path d={svgPath} />
</svg>
<span class="font-heading font-semibold text-xl text-text"></span>
<span><span></span></span>
</div>
<div class="container-right">
<a href="/"></a>
<a href="/history"></a>
<a href="/" onClick={handleNavColor}></a>
<a href="/history" onClick={handleNavColor}></a>
<button onClick={handleClick}></button>
</div>
</div>
</nav>
)
}
}
export default Navbar
+1 -1
View File
@@ -1,5 +1,5 @@
import { Router, Route } from "preact-router"
import { Navbar } from "../components/Navbar"
import Navbar from "../components/Navbar"
import Main from "../components/Main"
import History from "../components/History"
import { Footer } from "../components/Footer"
+55 -14
View File
@@ -1,4 +1,5 @@
html
font-size: 16px
text-align: center
color: white
@@ -8,6 +9,39 @@ body
font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI"
overflow: hidden
body, ul, ol, li, p, h1, h2, h3, h4, h5, h6,
form, fieldset, img, div, pre
margin: 0
padding: 0
outline: 0
border: 0
ul, li, ol
list-style-type: none
select, textarea, button
background: transparent
border: none
outline: none
button:focus,input:focus, code:focus, pre:focus, video
outline: none
button, i, img
cursor: pointer
user-select: none
-webkit-user-select: none
-moz-user-select: none
-khtml-user-select: none
-ms-user-select: none
a
text-decoration: none
color: #5470c6
.hidden
display: none
@font-face
font-family: "Nunito"
font-style: normal
@@ -44,8 +78,7 @@ body
display: inline-flex
align-items: center
justify-content: space-between
width: 100%
margin: 0 auto
width: calc(100% - 2.4rem)
padding: 0.6rem 1.2rem
background-color: white
backdrop-filter: blur(8px)
@@ -57,13 +90,20 @@ body
display: flex
align-items: center
gap: 0.75rem
cursor: pointer
.icon
width: 2rem
height: 2rem
color: var(--primary)
> span
font-weight: 600
font-size: 1.25rem
color: var(--title)
> span
color: var(--primary)
.container-right
display: flex
align-items: center
@@ -76,8 +116,8 @@ body
font-size: 0.9375rem
cursor: pointer
&:hover
color: var(--primary)
.active
color: var(--primary)
> button
width: 7rem
@@ -183,6 +223,8 @@ body
color: var(--textsub)
#previewContent
display: flex
flex-direction: column
margin-top: 0.5rem
> img
@@ -213,10 +255,9 @@ body
width: 4rem
height: 4rem
margin: 0 auto 1rem auto
border-width: 4px
border-color: var(--primary)
border: 0.25rem solid var(--primary)
border-top-color: transparent
border-radius: 4rem
border-radius: 50%
animation: spin 1s linear infinite
@keyframes spin
@@ -257,6 +298,7 @@ body
.result
width: 35rem
height: 1.5rem
margin: 0 auto
.result-complete
@@ -275,7 +317,7 @@ body
> h2
font-family: "SANS_SC_BOLD"
font-weight: bold
font-size: 1.5rem
font-size: 1.375rem
color: var(--title)
.result-main
@@ -286,11 +328,11 @@ body
background-color: white
border-radius: 1rem
border: 1px solid var(--color-border)
gap: 2rem
gap: 1.5rem
> img
width: 8rem
height: 8rem
max-width: 8rem
max-height: 8rem
background-color: #333
border-radius: 0.5rem
@@ -299,7 +341,7 @@ body
flex-direction: column
justify-content: flex-start
align-items: flex-start
width: calc(100% - 10rem)
width: calc(100% - 9.5rem)
> div
display: flex
@@ -377,7 +419,6 @@ body
justify-content: center
position: fixed
width: 100vw
height: 5rem
background-color: #131313
padding: 2rem 1rem
bottom: 0
+28 -5
View File
@@ -34,7 +34,7 @@
display: flex
justify-content: space-between
width: calc(100% - 20rem)
height: 5rem
height: 3rem
padding: 1rem
margin-bottom: 0.6rem
background-color: #FFFFFF
@@ -49,16 +49,22 @@
align-items: center
width: 3rem
height: 3rem
background-color: #333333
background-image: conic-gradient(#f0f0f0 0% 25%, transparent 0% 50%, #f0f0f0 50% 75%, transparent 0% 100%)
background-size: 20px 20px
opacity: 1
border-radius: 0.5rem
overflow: hidden
position: relative
> img
max-width: 100%
max-height: 100%
width: 100%
height: 100%
object-fit: cover
.card-right
display: flex
flex-direction: column
width: calc(100% - 5rem)
width: calc(100% - 4rem)
height: 5rem
.right-top
@@ -112,4 +118,21 @@
width: calc(100% - 20rem)
margin-top: 0.6rem
.history-none
display: flex
flex-direction: column
justify-content: center
align-items: center
align-content: center
margin-top: 12rem
> svg
width: 4rem
height: 4rem
> p
text-align: center
font-size: 0.825rem
color: #c0c0c0