frontend finishded

This commit is contained in:
2026-07-22 17:48:49 +08:00
parent 6f6bde4a24
commit 9f313a54b1
17 changed files with 284 additions and 76 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

+79 -38
View File
@@ -1,6 +1,9 @@
import { useState, useEffect } from 'preact/hooks'
import { message } from '../utils/toast'
import Pagination from './Pagination'
import Modal from './Modal'
import type { HistoryItem } from '../preact'
const formatDate = (timestamp: number) => {
const date = new Date(timestamp * 1000)
@@ -14,20 +17,14 @@ const formatDate = (timestamp: number) => {
})
}
interface IHistoryItem {
id: number
img: string
breed: number
date: number
name: string
brief: string
}
const History = () => {
const [page, setPage] = useState<number>(1)
const pageSize = 5
const [total, setTotal] = useState<number>(50)
const [historyList, setHistoryList] = useState<IHistoryItem[]>([])
const [historyList, setHistoryList] = useState<HistoryItem[]>([])
const [showDelete, setShowDelete] = useState<boolean>(false)
const [currentId, setCurrentId] = useState<number | null>(null)
const [showClear, setShowClear] = useState<boolean>(false)
useEffect(() => {
if (!(window as any).go?.main?.App?.GetHistory) {
@@ -52,46 +49,90 @@ const History = () => {
fetchData(page)
}
const handleDelete = async(id: number) => {
const result = await (window as any).go.main.App.DeleteOneHistory(id)
const handleShowDelete = (id: number) => {
setCurrentId(id)
setShowDelete(true)
}
const handleDeleteOk = async() => {
setShowDelete(false)
if (!currentId) {
message.error('currentId为空')
return
}
const result = await (window as any).go.main.App.DeleteOneHistory(currentId)
if (result.code === 0) {
message.success('删除成功')
setCurrentId(null)
fetchData(page)
} else if (result.code === 1) {
message.error(result.message)
}
}
const handleDeleteClose = () => {
setShowDelete(false)
setCurrentId(null)
}
const handleShowModal = () => setShowClear(true)
const handleClearOk = async() => {
setShowClear(false)
const result = await (window as any).go.main.App.ClearHistory()
if (result.code === 0) {
message.success('已清空历史')
setCurrentId(null)
fetchData(page)
} else if (result.code === 1) {
message.error(result.message)
}
}
const handleClearClose = () => setShowClear(false)
return (
<div class="app-history">
<div class="history-clear">
<a></a>
</div>
{historyList.map((item: IHistoryItem) =>
<div key={item.id} class="history-card">
<div class="card-left">
<img src="../assets/images/0012.jpg" />
</div>
<div class="card-right">
<div class="right-top">
<h3>{item.name}</h3>
<div class="card-actions">
<span>{formatDate(item.date)}</span>
<button onClick={() => handleDelete(item.id)} title="删除">
×
</button>
<>
<div class="app-history">
<div class="history-clear">
<button onClick={handleShowModal} title="清空历史">
<svg class="icon" viewBox="0 0 24 24" fill="#616569ff" width="16" height="16">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
</svg>
</button>
</div>
{historyList.map((item: HistoryItem) =>
<div key={item.id} class="history-card">
<div class="card-left">
<img src="/images/0012.jpg" alt="" />
</div>
<div class="card-right">
<div class="right-top">
<h3>{item.name}</h3>
<div class="card-actions">
<span>{formatDate(item.date)}</span>
<button onClick={() => handleShowDelete(item.id)} title="删除">
×
</button>
</div>
</div>
<div class="right-overview">
{item.brief}
</div>
</div>
<div class="right-overview">
{item.brief}
</div>
</div>
</div>)
}
<div class="history-pagination">
<Pagination page={page} pagesize={pageSize} total={total} onChange={handlePageChange} />
</div>)
}
<div class="history-pagination">
<Pagination page={page} pagesize={pageSize} total={total} onChange={handlePageChange} />
</div>
</div>
</div>
<Modal open={showDelete} title="信息" onClick={handleDeleteOk} onClose={handleDeleteClose}>
<p></p>
</Modal>
<Modal open={showClear} title="信息" onClick={handleClearOk} onClose={handleClearClose}>
<p></p>
</Modal>
</>
)
}
+9 -19
View File
@@ -1,24 +1,18 @@
import { useState, useRef } from 'preact/hooks'
import { message } from '../utils/toast'
import type { DetectResult } from '../preact'
interface IDetectResult {
id: number
code: string
name: number
brief: string
confidence_level: number
}
const Main = () => {
const fileInputRef = useRef<HTMLInputElement>(null)
const [fileName, setFileName] = useState<string>('')
const [fileSrc, setFileSrc] = useState<string>('')
const [step, setStep] = useState<number>(0)
const [detectResult, setDetectResult] = useState<IDetectResult | null>(null)
const [detectResult, setDetectResult] = useState<DetectResult | null>(null)
const handleUploadClick = () => fileInputRef.current?.click()
const handleFileChange = (e: Event) => {
console.log('handleFileChange')
const target = e.target as HTMLInputElement
const file = target.files?.[0]
if (file) {
@@ -31,15 +25,11 @@ const Main = () => {
Array.from(uint8Array),
file.name
)
if (result.code === 0) {
setFileName(result.data)
const imgResult = await (window as any).go.main.App.GetImage(result.data)
if (imgResult.code === 0) {
setFileSrc(imgResult.data)
setStep(1)
}
setFileSrc(result.data)
setStep(1)
} else if (result.code === 1) {
message.error(result.message)
}
}
reader.readAsArrayBuffer(file)
@@ -63,7 +53,7 @@ const Main = () => {
setStep(2)
setTimeout(async() => {
const result = await (window as any).go.main.App.Detect(fileName)
const result = await (window as any).go.main.App.Detect(fileSrc)
if (result.code === 0) {
setDetectResult(result.data)
setStep(3)
@@ -104,7 +94,7 @@ const Main = () => {
>
{fileSrc.length > 0 && step == 1 ?
<div id="previewContent">
<img src={fileSrc} id="previewImage" />
<img src={`/images/${fileSrc}`} id="previewImage" />
<button onClick={handleRemovePhoto}>
</button>
+41
View File
@@ -0,0 +1,41 @@
import type { ModalProps } from '../preact'
const Modal = ({ open, title, onClick, onClose, children }: ModalProps) => {
const handleClose = () => {
onClose?.()
}
const handleConfirm = () => {
onClick?.()
handleClose()
}
const handleMaskClick = (e: MouseEvent) => {
if (e.target === e.currentTarget) {
handleClose()
}
}
return (
<>
{open ?
<>
<div class="app-modal" onClick={handleMaskClick}>
<div class="title">
<h3>{title}</h3>
<span onClick={handleClose}>×</span>
</div>
{children}
<div class="bottom">
<button onClick={handleClose}></button>
<button onClick={handleConfirm}></button>
</div>
</div>
<div class="app-mask" onClick={handleMaskClick}></div>
</> : null
}
</>
)
}
export default Modal
+2 -7
View File
@@ -1,18 +1,13 @@
import { useState, useEffect } from 'preact/hooks'
import type { PaginationProps } from '../preact'
interface IPagination {
total: number
onChange: (page: number) => void
page: number
pagesize: number
}
const Pagination = ({
total,
onChange,
page,
pagesize,
}: IPagination) => {
}: PaginationProps) => {
const [value, setValue] = useState<string>('1')
const [num, setNum] = useState<number>(1)
const [seqNums, setSeqNums] = useState<[number, number][]>([])
+31
View File
@@ -0,0 +1,31 @@
export interface HistoryItem {
id: number
img: string
breed: number
date: number
name: string
brief: string
}
export interface DetectResult {
id: number
code: string
name: number
brief: string
confidence_level: number
}
export interface PaginationProps {
total: number
onChange: (page: number) => void
page: number
pagesize: number
}
interface ModalProps {
open: boolean
title: string
onClick?: () => void
onClose?: () => void
children?: preact.ComponentChildren
}
+66
View File
@@ -387,6 +387,72 @@ body
font-size: 0.8rem
margin: 0 0.5rem
.app-modal
width: 20rem
padding: 0.75rem 1.25rem
position: fixed
top: 14rem
left: calc(50% - 10rem)
background-color: white
border-radius: 0.5rem
z-index: 1002
.title
display: flex
justify-content: space-between
align-items: center
> h3
text-align: left
color: var(--title)
font-size: 1rem
font-weight: bold
> span
color: #9ca3af
font-size: 1.25rem
cursor: pointer
> p
padding: 1rem 0rem
margin-bottom: 0.5rem
color: var(--text)
font-size: 0.9375rem
text-align: left
.bottom
display: flex
justify-content: flex-end
margin-bottom: 0.25rem
gap: 0.5rem
> button
width: 4.5rem
height: 1.875rem
font-size: 0.875rem
border-radius: 0.25rem
&:first-child
color: var(--text)
border: 1px solid #c9c9c9
background-color: none
&:last-child
color: white
background-color: var(--primary)
.app-mask
width: 100%
height: 100vh
position: fixed
top: 0
left: 0
background-color: black
opacity: 0.5
z-index: 1001
.message
width: 100%
height: 2rem
+29 -9
View File
@@ -3,18 +3,32 @@
flex-direction: column
align-items: center
height: 651px
padding: 6.5rem 1rem 4rem 1rem
padding: 7.25rem 1rem 4rem 1rem
.history-clear
width: calc(100% - 20rem)
text-align: right
display: flex
justify-content: flex-end
align-items: center
margin-bottom: 0.5rem
position: absolute
top: 19rem
right: 1rem
z-index: 1000
> a
font-size: 0.875rem
color: var(--primary)
> button
display: flex
justify-content: center
align-items: center
padding: 0.75rem
background-color: white
backdrop-filter: blur(8px)
border-radius: 0.375rem
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)
border: 1px solid transparent
cursor: pointer
// text-decoration: underline
> svg
cursor: pointer
.history-card
display: flex
@@ -30,10 +44,17 @@
border: 1px solid var(--border)
.card-left
display: flex
justify-content: center
align-items: center
width: 3rem
height: 3rem
background-color: #333333
> img
max-width: 100%
max-height: 100%
.card-right
display: flex
flex-direction: column
@@ -74,7 +95,6 @@
padding: 0
background: none
border: none
border-radius: 0.35rem
color: #9ca3af
cursor: pointer
@@ -90,6 +110,6 @@
.history-pagination
width: calc(100% - 20rem)
margin-top: 0.5rem
margin-top: 0.6rem