diff --git a/app.db b/app.db index dca7027..1d79e28 100644 Binary files a/app.db and b/app.db differ diff --git a/app.go b/app.go index 3d8a6f9..52991ae 100644 --- a/app.go +++ b/app.go @@ -12,6 +12,10 @@ import ( "gorm.io/gorm" ) +var ( + publicImagePath = "./frontend/public/images" +) + func NewApp() *App { return &App{} } @@ -33,7 +37,7 @@ func (a *App) GormDB() (*gorm.DB, error) { } func (a *App) UploadImage(data []byte, filename string) Response { - uploadsDir := "./uploads" + uploadsDir := publicImagePath err := os.MkdirAll(uploadsDir, 0755) if err != nil { return Response{Code: 1, Message: "failed", Data: err.Error()} @@ -52,7 +56,7 @@ func (a *App) UploadImage(data []byte, filename string) Response { } func (a *App) GetImage(filename string) Response { - filePath := filepath.Join("./uploads", filename) + filePath := filepath.Join(publicImagePath, filename) data, err := os.ReadFile(filePath) if err != nil { @@ -139,3 +143,17 @@ func (a *App) DeleteOneHistory(id uint) Response { return Response{Code: 0, Message: "success"} } + +func (a *App) ClearHistory() Response { + db, err := a.GormDB() + if err != nil { + return Response{Code: 1, Message: err.Error()} + } + + result := db.Exec("DELETE FROM history_test") + if result.Error != nil { + return Response{Code: 1, Message: result.Error.Error()} + } + + return Response{Code: 0, Message: "success"} +} diff --git a/frontend/package.json.md5 b/frontend/package.json.md5 index 57290e4..6183add 100644 --- a/frontend/package.json.md5 +++ b/frontend/package.json.md5 @@ -1 +1 @@ -d517c8a0f1aee8820be9290e2d54cb8b \ No newline at end of file +f535f0817b95f10a6229620a63d82985 \ No newline at end of file diff --git a/frontend/src/assets/images/0012.jpg b/frontend/public/images/0012.jpg similarity index 100% rename from frontend/src/assets/images/0012.jpg rename to frontend/public/images/0012.jpg diff --git a/frontend/public/images/1784707678705.jpg b/frontend/public/images/1784707678705.jpg new file mode 100644 index 0000000..1f51ca5 Binary files /dev/null and b/frontend/public/images/1784707678705.jpg differ diff --git a/frontend/src/assets/fonts/HARMONYOS_SANS_SC_REGULAR.TTF b/frontend/src/assets/fonts/HARMONYOS_SANS_SC_REGULAR.TTF deleted file mode 100644 index 95b29bc..0000000 Binary files a/frontend/src/assets/fonts/HARMONYOS_SANS_SC_REGULAR.TTF and /dev/null differ diff --git a/frontend/src/assets/images/组合 2.png b/frontend/src/assets/images/组合 2.png deleted file mode 100644 index c6da4bb..0000000 Binary files a/frontend/src/assets/images/组合 2.png and /dev/null differ diff --git a/frontend/src/assets/menu-icon.ico b/frontend/src/assets/menu-icon.ico deleted file mode 100644 index 0ffa881..0000000 Binary files a/frontend/src/assets/menu-icon.ico and /dev/null differ diff --git a/frontend/src/components/History.tsx b/frontend/src/components/History.tsx index 7d66773..f15250c 100644 --- a/frontend/src/components/History.tsx +++ b/frontend/src/components/History.tsx @@ -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(1) const pageSize = 5 const [total, setTotal] = useState(50) - const [historyList, setHistoryList] = useState([]) + const [historyList, setHistoryList] = useState([]) + const [showDelete, setShowDelete] = useState(false) + const [currentId, setCurrentId] = useState(null) + const [showClear, setShowClear] = useState(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 ( -
- - {historyList.map((item: IHistoryItem) => -
-
- -
-
-
-

{item.name}

-
- {formatDate(item.date)} - + <> +
+
+ +
+ {historyList.map((item: HistoryItem) => +
+
+ +
+
+
+

{item.name}

+
+ {formatDate(item.date)} + +
+
+
+ {item.brief}
-
- {item.brief} -
-
-
) - } -
- +
) + } +
+ +
-
+ +

确定要删除当前记录?

+
+ +

确定要删除全部记录?

+
+ ) } diff --git a/frontend/src/components/Main.tsx b/frontend/src/components/Main.tsx index 33db2dd..83f1635 100644 --- a/frontend/src/components/Main.tsx +++ b/frontend/src/components/Main.tsx @@ -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(null) - const [fileName, setFileName] = useState('') const [fileSrc, setFileSrc] = useState('') const [step, setStep] = useState(0) - const [detectResult, setDetectResult] = useState(null) + const [detectResult, setDetectResult] = useState(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 ?
- + diff --git a/frontend/src/components/Modal.tsx b/frontend/src/components/Modal.tsx new file mode 100644 index 0000000..2d91016 --- /dev/null +++ b/frontend/src/components/Modal.tsx @@ -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 ? + <> +
+
+

{title}

+ × +
+ {children} +
+ + +
+
+
+ : null + } + + ) +} + +export default Modal \ No newline at end of file diff --git a/frontend/src/components/Pagination.tsx b/frontend/src/components/Pagination.tsx index 50daefd..4accddb 100644 --- a/frontend/src/components/Pagination.tsx +++ b/frontend/src/components/Pagination.tsx @@ -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('1') const [num, setNum] = useState(1) const [seqNums, setSeqNums] = useState<[number, number][]>([]) diff --git a/frontend/src/preact.d.ts b/frontend/src/preact.d.ts index e69de29..d1434a7 100644 --- a/frontend/src/preact.d.ts +++ b/frontend/src/preact.d.ts @@ -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 +} \ No newline at end of file diff --git a/frontend/src/styles/base.sass b/frontend/src/styles/base.sass index 3fe644c..2b3b8b1 100644 --- a/frontend/src/styles/base.sass +++ b/frontend/src/styles/base.sass @@ -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 diff --git a/frontend/src/styles/history.sass b/frontend/src/styles/history.sass index 29c1829..76f0b7a 100644 --- a/frontend/src/styles/history.sass +++ b/frontend/src/styles/history.sass @@ -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 diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 0898305..22e9028 100644 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -3,6 +3,8 @@ import {main} from '../models'; import {gorm} from '../models'; +export function ClearHistory():Promise; + export function DeleteOneHistory(arg1:number):Promise; export function Detect(arg1:string):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index af0f25a..398a6ba 100644 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -2,6 +2,10 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +export function ClearHistory() { + return window['go']['main']['App']['ClearHistory'](); +} + export function DeleteOneHistory(arg1) { return window['go']['main']['App']['DeleteOneHistory'](arg1); }