much
This commit is contained in:
+12
-12
@@ -9,18 +9,18 @@
|
|||||||
tailwind.config = {
|
tailwind.config = {
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
primary: '#3B82F6',
|
primary: '#3B82F6',
|
||||||
secondary: '#60A5FA',
|
secondary: '#60A5FA',
|
||||||
cta: '#F97316',
|
cta: '#F97316',
|
||||||
background: '#F8FAFC',
|
background: '#F8FAFC',
|
||||||
text: '#1E293B',
|
text: '#1E293B',
|
||||||
border: '#E2E8F0',
|
border: '#E2E8F0',
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
heading: ['Fredoka', 'sans-serif'],
|
heading: ['Fredoka', 'sans-serif'],
|
||||||
body: ['Nunito', 'sans-serif'],
|
body: ['Nunito', 'sans-serif'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+10
@@ -9,6 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"preact": "^10.10.1",
|
"preact": "^10.10.1",
|
||||||
|
"preact-router": "^4.1.2",
|
||||||
"sass": "^1.101.0"
|
"sass": "^1.101.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -1949,6 +1950,15 @@
|
|||||||
"url": "https://opencollective.com/preact"
|
"url": "https://opencollective.com/preact"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/preact-router": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/preact-router/-/preact-router-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-uICUaUFYh+XQ+6vZtQn1q+X6rSqwq+zorWOCLWPF5FAsQh3EJ+RsDQ9Ee+fjk545YWQHfUxhrBAaemfxEnMOUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"preact": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"preact": "^10.10.1",
|
"preact": "^10.10.1",
|
||||||
|
"preact-router": "^4.1.2",
|
||||||
"sass": "^1.101.0"
|
"sass": "^1.101.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
98b72ac08f2cce2880f36490b4944ea2
|
d517c8a0f1aee8820be9290e2d54cb8b
|
||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,18 @@
|
|||||||
|
import { route } from "preact-router"
|
||||||
|
|
||||||
|
const Dashboard = () => {
|
||||||
|
return (
|
||||||
|
<div class="app-dashboard">
|
||||||
|
<div class="dashboard-sidebar">
|
||||||
|
<a href="/dashboard/datasets" onClick={(e) => { e.preventDefault(); route("/dashboard/datasets") }}>训练集管理</a>
|
||||||
|
<a href="/dashboard/testsets" onClick={(e) => { e.preventDefault(); route("/dashboard/testsets") }}>测试集管理</a>
|
||||||
|
<a href="/dashboard/logs" onClick={(e) => { e.preventDefault(); route("/dashboard/logs") }}>训练日志</a>
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-content">
|
||||||
|
{/* 子页面内容通过 Router 渲染到这里 */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Dashboard
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
export const Footer = () => {
|
export const Footer = () => {
|
||||||
return (
|
return (
|
||||||
<footer class="h-[120px] bg-black border-t border-border py-8 px-4 md:px-6 lg:px-8">
|
<footer class="app-footer">
|
||||||
<div class="max-w-6xl mx-auto text-center">
|
<span>https://pytorch.org/</span>
|
||||||
<p class="text-text/50 text-sm">Made with ❤️ for cat lovers everywhere</p>
|
<span>|</span>
|
||||||
</div>
|
<span>https://wails.io/</span>
|
||||||
|
<span>|</span>
|
||||||
|
<span>https://preactjs.com/</span>
|
||||||
</footer>
|
</footer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import { useState, useEffect } from 'preact/hooks'
|
||||||
|
import Pagination from './Pagination'
|
||||||
|
|
||||||
|
const History = () => {
|
||||||
|
const [page, setPage] = useState<number>(1)
|
||||||
|
const [total, setTotal] = useState<number>(50)
|
||||||
|
|
||||||
|
|
||||||
|
const handlePageChange = (page: number) => {
|
||||||
|
// setPage(page)
|
||||||
|
// loadTranscript(currentNav, currentOpt, page).then(res => {
|
||||||
|
// if (res && res.code === 0) {
|
||||||
|
// setData(res.data.data)
|
||||||
|
// setTotal(res.data.total)
|
||||||
|
// }
|
||||||
|
// }).catch(e => message.error(e.toString()))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="app-history">
|
||||||
|
<div class="history-card">
|
||||||
|
<div class="card-left">
|
||||||
|
<img src="../assets/images/0012.jpg" />
|
||||||
|
</div>
|
||||||
|
<div class="card-right">
|
||||||
|
<div class="right-top">
|
||||||
|
<h3>Maine Coon</h3>
|
||||||
|
<span>Jan 15, 2024</span>
|
||||||
|
</div>
|
||||||
|
<div class="right-overview">
|
||||||
|
The Maine Coon is a large, friendly cat breed known for its tufted ears.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="history-card">
|
||||||
|
<div class="card-left">
|
||||||
|
<img src="../assets/images/0012.jpg" />
|
||||||
|
</div>
|
||||||
|
<div class="card-right">
|
||||||
|
<div class="right-top">
|
||||||
|
<h3>Maine Coon</h3>
|
||||||
|
<span>Jan 15, 2024</span>
|
||||||
|
</div>
|
||||||
|
<div class="right-overview">
|
||||||
|
The Maine Coon is a large, friendly cat breed known for its tufted ears.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="history-card">
|
||||||
|
<div class="card-left">
|
||||||
|
<img src="../assets/images/0012.jpg" />
|
||||||
|
</div>
|
||||||
|
<div class="card-right">
|
||||||
|
<div class="right-top">
|
||||||
|
<h3>Maine Coon</h3>
|
||||||
|
<span>Jan 15, 2024</span>
|
||||||
|
</div>
|
||||||
|
<div class="right-overview">
|
||||||
|
The Maine Coon is a large, friendly cat breed known for its tufted ears.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="history-card">
|
||||||
|
<div class="card-left">
|
||||||
|
<img src="../assets/images/0012.jpg" />
|
||||||
|
</div>
|
||||||
|
<div class="card-right">
|
||||||
|
<div class="right-top">
|
||||||
|
<h3>Maine Coon</h3>
|
||||||
|
<span>Jan 15, 2024</span>
|
||||||
|
</div>
|
||||||
|
<div class="right-overview">
|
||||||
|
The Maine Coon is a large, friendly cat breed known for its tufted ears.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="history-card">
|
||||||
|
<div class="card-left">
|
||||||
|
<img src="../assets/images/0012.jpg" />
|
||||||
|
</div>
|
||||||
|
<div class="card-right">
|
||||||
|
<div class="right-top">
|
||||||
|
<h3>Maine Coon</h3>
|
||||||
|
<span>Jan 15, 2024</span>
|
||||||
|
</div>
|
||||||
|
<div class="right-overview">
|
||||||
|
The Maine Coon is a large, friendly cat breed known for its tufted ears.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="history-pagination">
|
||||||
|
<Pagination page={page} pagesize={5} total={total} onChange={handlePageChange} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default History
|
||||||
@@ -1,39 +1,38 @@
|
|||||||
export const Main = () => {
|
const Main = () => {
|
||||||
return (
|
return (
|
||||||
<main class="h-[648px] pt-28 pb-16 px-4 md:px-6 lg:px-8">
|
<main class="app-main">
|
||||||
<div class="max-w-6xl mx-auto">
|
<div class="main-container">
|
||||||
{/* <div class="text-center mb-12 animate-slide-up">
|
<div class="title">
|
||||||
<h1 class="font-heading font-bold text-4xl md:text-5xl lg:text-6xl text-text mb-4">
|
<h1>
|
||||||
Discover Your Cat's <span class="text-primary">Breed</span>
|
发现<span>它</span>的<span>分类</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p class="font-body text-lg md:text-xl text-text/70 max-w-2xl mx-auto">
|
<p>
|
||||||
Upload a photo of your furry friend and let our AI identify their breed in seconds
|
上传一张猫咪照片,让AI不仅认出它<span>是什么</span>
|
||||||
</p>
|
</p>
|
||||||
</div> */}
|
<i>基于深度残差网络</i>
|
||||||
|
</div>
|
||||||
{/* <div class="max-w-2xl mx-auto mb-12 animate-slide-up" style="animation-delay: 0.1s;">
|
<div class="upload">
|
||||||
<div
|
<div
|
||||||
id="dropZone"
|
id="dropZone"
|
||||||
class="drop-zone bg-white rounded-3xl border-2 border-dashed border-border p-12 text-center cursor-pointer"
|
class="upload-zone"
|
||||||
>
|
>
|
||||||
<div id="uploadContent">
|
<div id="uploadContent">
|
||||||
<svg class="w-16 h-16 mx-auto mb-4 text-secondary animate-pulse-slow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
<svg class="w-16 h-16 mx-auto mb-4 text-secondary animate-pulse-slow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 16.5V9.75m0 0l3 3m-3-3l-3 3M6.75 19.5a4.5 4.5 0 01-1.41-8.775 5.25 5.25 0 0110.233-2.33 3 3 0 013.758 3.848A3.752 3.752 0 0118 19.5H6.75z" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 16.5V9.75m0 0l3 3m-3-3l-3 3M6.75 19.5a4.5 4.5 0 01-1.41-8.775 5.25 5.25 0 0110.233-2.33 3 3 0 013.758 3.848A3.752 3.752 0 0118 19.5H6.75z" />
|
||||||
</svg>
|
</svg>
|
||||||
<p class="font-heading font-semibold text-xl text-text mb-2">Drop your cat's photo here</p>
|
<p class="font-heading font-semibold text-xl text-text mb-2">点击或拖拽上传</p>
|
||||||
<p class="text-text/60 mb-4">or click to browse</p>
|
<p class="text-sm text-text/50">支持JPG、PNG、JPEG,最大不超过2MB</p>
|
||||||
<p class="text-sm text-text/50">Supports JPG, PNG up to 10MB</p>
|
</div>
|
||||||
</div>
|
{/* <div id="previewContent" class="hidden">
|
||||||
<div id="previewContent" class="hidden">
|
<img id="previewImage" class="max-h-64 mx-auto rounded-2xl mb-4 object-cover" alt="Cat preview" />
|
||||||
<img id="previewImage" class="max-h-64 mx-auto rounded-2xl mb-4 object-cover" alt="Cat preview" />
|
<button id="removeBtn" class="text-red-500 hover:text-red-600 font-medium transition-colors duration-200 cursor-pointer">
|
||||||
<button id="removeBtn" class="text-red-500 hover:text-red-600 font-medium transition-colors duration-200 cursor-pointer">
|
Remove photo
|
||||||
Remove photo
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
<input type="file" id="fileInput" class="hidden" accept="image/*" /> */}
|
||||||
<input type="file" id="fileInput" class="hidden" accept="image/*" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
{/* <button
|
||||||
id="detectBtn"
|
id="detectBtn"
|
||||||
class="hidden w-full mt-4 bg-cta hover:bg-orange-600 text-white font-heading font-semibold text-lg py-4 rounded-2xl transition-colors duration-200 cursor-pointer flex items-center justify-center gap-3"
|
class="hidden w-full mt-4 bg-cta hover:bg-orange-600 text-white font-heading font-semibold text-lg py-4 rounded-2xl transition-colors duration-200 cursor-pointer flex items-center justify-center gap-3"
|
||||||
>
|
>
|
||||||
@@ -41,8 +40,8 @@ export const Main = () => {
|
|||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456z" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456z" />
|
||||||
</svg>
|
</svg>
|
||||||
Detect Breed
|
Detect Breed
|
||||||
</button>
|
</button> */}
|
||||||
</div> */}
|
</div>
|
||||||
|
|
||||||
{/* <div id="loadingState" class="hidden max-w-2xl mx-auto mb-12">
|
{/* <div id="loadingState" class="hidden max-w-2xl mx-auto mb-12">
|
||||||
<div class="bg-white rounded-3xl border border-border p-8 text-center">
|
<div class="bg-white rounded-3xl border border-border p-8 text-center">
|
||||||
@@ -60,7 +59,7 @@ export const Main = () => {
|
|||||||
<h2 class="font-heading font-bold text-2xl text-text">Detection Complete!</h2>
|
<h2 class="font-heading font-bold text-2xl text-text">Detection Complete!</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="primaryResult" class="bg-white rounded-3xl border border-border p-6 md:p-8 mb-6 animate-slide-up">
|
<div id="primaryResult" class="bg-white rounded-3xl border border-border p-6 md:p-8 mb-6">
|
||||||
<div class="flex flex-col md:flex-row gap-6 md:gap-8">
|
<div class="flex flex-col md:flex-row gap-6 md:gap-8">
|
||||||
<div class="flex-shrink-0">
|
<div class="flex-shrink-0">
|
||||||
<img id="resultImage" class="w-full md:w-48 h-48 rounded-2xl object-cover" alt="Cat photo" />
|
<img id="resultImage" class="w-full md:w-48 h-48 rounded-2xl object-cover" alt="Cat photo" />
|
||||||
@@ -141,4 +140,6 @@ export const Main = () => {
|
|||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Main
|
||||||
@@ -1,21 +1,22 @@
|
|||||||
export const Navbar = () => {
|
export 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/Leon/Collage-Images', '_blank')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav class="fixed top-4 left-4 right-4 z-50 animate-fade-in">
|
<nav class="app-navbar animate-fade-in">
|
||||||
<div class="max-w-6xl mx-auto bg-white backdrop-blur-md rounded-2xl shadow-lg border border-border px-6 py-4">
|
<div class="navbar-container">
|
||||||
<div class="flex items-center justify-between">
|
<div class="container-left">
|
||||||
<div class="flex items-center gap-3 cursor-pointer">
|
<svg class="icon" viewBox="0 0 24 24" fill="currentColor">
|
||||||
<svg class="w-8 h-8 text-primary" viewBox="0 0 24 24" fill="currentColor">
|
<path d={svgPath} />
|
||||||
<path d="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"/>
|
</svg>
|
||||||
</svg>
|
<span class="font-heading font-semibold text-xl text-text">分类miao</span>
|
||||||
<span class="font-heading font-semibold text-xl text-text">MeowVision</span>
|
</div>
|
||||||
</div>
|
<div class="container-right">
|
||||||
<div class="flex items-center gap-6">
|
<a href="/">主页</a>
|
||||||
<a href="#" class="text-text/70 hover:text-primary transition-colors duration-200 font-medium cursor-pointer">数据集</a>
|
<a href="/history">历史记录</a>
|
||||||
<a href="#" class="text-text/70 hover:text-primary transition-colors duration-200 font-medium cursor-pointer">历史记录</a>
|
<a href="/dashboard">后台管理</a>
|
||||||
<button class="bg-primary hover:bg-blue-600 text-white px-5 py-2.5 rounded-xl font-semibold transition-colors duration-200 cursor-pointer">
|
<button onClick={handleClick}>代码仓库</button>
|
||||||
代码仓库
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -0,0 +1,214 @@
|
|||||||
|
import { useState, useEffect } from 'preact/hooks'
|
||||||
|
|
||||||
|
interface IPagination {
|
||||||
|
total: number
|
||||||
|
onChange: (page: number) => void
|
||||||
|
page: number
|
||||||
|
pagesize: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const Pagination = ({
|
||||||
|
total,
|
||||||
|
onChange,
|
||||||
|
page,
|
||||||
|
pagesize,
|
||||||
|
}: IPagination) => {
|
||||||
|
const [value, setValue] = useState<string>('1')
|
||||||
|
const [num, setNum] = useState<number>(1)
|
||||||
|
const [seqNums, setSeqNums] = useState<[number, number][]>([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setValue('1')
|
||||||
|
setNum(1)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (page) {
|
||||||
|
setValue(page.toString());
|
||||||
|
let nums: [number, number][] = []
|
||||||
|
for (let i = 1; i < total / pagesize + 1; i++) {
|
||||||
|
if (i === 1) {
|
||||||
|
nums.push([1, 1])
|
||||||
|
} else {
|
||||||
|
nums.push([i, 0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setSeqNums(nums)
|
||||||
|
calSeqNums(nums, page)
|
||||||
|
}
|
||||||
|
}, [total, page])
|
||||||
|
|
||||||
|
const handleChange = (e: Event) => {
|
||||||
|
const target = e.target as HTMLInputElement
|
||||||
|
setValue(target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEnterPress = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
if (parseInt(value) <= seqNums.length && parseInt(value) > 0) {
|
||||||
|
handleChangeNum(parseInt(value))
|
||||||
|
} else if (parseInt(value) >= seqNums.length) {
|
||||||
|
handleChangeNum(seqNums.length)
|
||||||
|
} else if (parseInt(value) < seqNums.length) {
|
||||||
|
handleChangeNum(1)
|
||||||
|
} else {
|
||||||
|
handleChangeNum(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const calSeqNums = (seqNums: [number, number][], num: number) => {
|
||||||
|
const seqNumsTemp = seqNums.map((item): [number, number] =>
|
||||||
|
item[0] === num ? [item[0], 1] : [item[0], 0],
|
||||||
|
)
|
||||||
|
setSeqNums(seqNumsTemp)
|
||||||
|
setNum(num)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeNum = (val: number|string) => {
|
||||||
|
if (typeof val === 'number') {
|
||||||
|
setValue(String(val))
|
||||||
|
if (val !== num) onChange(val)
|
||||||
|
calSeqNums(seqNums, val)
|
||||||
|
} else if (typeof val === 'string') {
|
||||||
|
if (val === 'pre') {
|
||||||
|
if (num > 1) {
|
||||||
|
calSeqNums(seqNums, num - 1)
|
||||||
|
setValue(String(num - 1))
|
||||||
|
onChange(num - 1)
|
||||||
|
}
|
||||||
|
} else if (val === 'next') {
|
||||||
|
if (num < seqNums.length) {
|
||||||
|
calSeqNums(seqNums, num + 1)
|
||||||
|
setValue(String(num + 1))
|
||||||
|
onChange(num + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const calPaginationDom = () => {
|
||||||
|
return seqNums.map((item) => (
|
||||||
|
<span
|
||||||
|
key={item[0]}
|
||||||
|
className={`pagination-num${
|
||||||
|
item[1] === 1 ? ' pagination-num-selected' : ''
|
||||||
|
}`}
|
||||||
|
onClick={() => handleChangeNum(item[0])}
|
||||||
|
>
|
||||||
|
{item[0]}
|
||||||
|
</span>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
const calPaginationDomEtc = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{num < 5 && (
|
||||||
|
<>
|
||||||
|
{seqNums.slice(0, 5).map((item) => (
|
||||||
|
<span
|
||||||
|
key={item[0]}
|
||||||
|
className={`pagination-num${
|
||||||
|
item[1] === 1 ? ' pagination-num-selected' : ''
|
||||||
|
}`}
|
||||||
|
onClick={() => handleChangeNum(item[0])}
|
||||||
|
>
|
||||||
|
{item[0]}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
<span className="pagination-etc"> ... </span>
|
||||||
|
<span
|
||||||
|
className="pagination-num"
|
||||||
|
onClick={() => handleChangeNum(seqNums.length)}
|
||||||
|
>
|
||||||
|
{seqNums.length}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{num >= 5 && num <= seqNums.length - 4 && (
|
||||||
|
<>
|
||||||
|
<span className="pagination-num" onClick={() => handleChangeNum(1)}>
|
||||||
|
1
|
||||||
|
</span>
|
||||||
|
<span className="pagination-etc"> ... </span>
|
||||||
|
{seqNums.slice(num - 3, num + 2).map((item) => (
|
||||||
|
<span
|
||||||
|
key={item[0]}
|
||||||
|
className={`pagination-num${
|
||||||
|
item[1] === 1 ? ' pagination-num-selected' : ''
|
||||||
|
}`}
|
||||||
|
onClick={() => handleChangeNum(item[0])}
|
||||||
|
>
|
||||||
|
{item[0]}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
<span className="pagination-etc"> ... </span>
|
||||||
|
<span
|
||||||
|
className="pagination-num"
|
||||||
|
onClick={() => handleChangeNum(seqNums.length)}
|
||||||
|
>
|
||||||
|
{seqNums.length}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{num > seqNums.length - 4 && (
|
||||||
|
<>
|
||||||
|
<span
|
||||||
|
key={1}
|
||||||
|
className="pagination-num"
|
||||||
|
onClick={() => handleChangeNum(1)}
|
||||||
|
>
|
||||||
|
1
|
||||||
|
</span>
|
||||||
|
<span className="pagination-etc"> ... </span>
|
||||||
|
{seqNums.slice(seqNums.length - 5, seqNums.length).map((item) => (
|
||||||
|
<span
|
||||||
|
key={item[0]}
|
||||||
|
className={`pagination-num${
|
||||||
|
item[1] === 1 ? ' pagination-num-selected' : ''
|
||||||
|
}`}
|
||||||
|
onClick={() => handleChangeNum(item[0])}
|
||||||
|
>
|
||||||
|
{item[0]}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="div-pagination">
|
||||||
|
<div className="div-pagination-core unselect">
|
||||||
|
<span
|
||||||
|
className="pagination-icon"
|
||||||
|
onClick={() => handleChangeNum('pre')}
|
||||||
|
>
|
||||||
|
{/* <img src="../static/images/page_left.svg" alt="" /> */}
|
||||||
|
◀
|
||||||
|
</span>
|
||||||
|
{seqNums.length < 10 ? calPaginationDom() : calPaginationDomEtc()}
|
||||||
|
<span
|
||||||
|
className="pagination-icon"
|
||||||
|
onClick={() => handleChangeNum('next')}
|
||||||
|
>
|
||||||
|
{/* <img src="../static/images/page_right.svg" alt="" /> */}
|
||||||
|
▶
|
||||||
|
</span>
|
||||||
|
<span className="pagination-word" style={{ marginLeft: 16 }}>
|
||||||
|
前往
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
value={value}
|
||||||
|
onChange={handleChange}
|
||||||
|
onKeyDown={handleEnterPress}
|
||||||
|
/>
|
||||||
|
<span className="pagination-word">页</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Pagination
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
const TestsetManagement = () => {
|
||||||
|
return (
|
||||||
|
<div></div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TestsetManagement
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
const TrainsetManagement = () => {
|
||||||
|
return (
|
||||||
|
<div></div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TrainsetManagement
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import {render} from 'preact';
|
import {render} from 'preact'
|
||||||
import {App} from './pages/App';
|
import {App} from './pages/App'
|
||||||
import './style.css';
|
|
||||||
|
|
||||||
render(<App/>, document.getElementById('app')!);
|
render(<App/>, document.getElementById('app')!)
|
||||||
|
|||||||
+19
-22
@@ -1,32 +1,29 @@
|
|||||||
|
import { Router, Route } from "preact-router"
|
||||||
|
import { Navbar } from "../components/Navbar"
|
||||||
import logo from "./assets/images/logo-universal.png"
|
import Main from "../components/Main"
|
||||||
import {Greet} from "../../wailsjs/go/main/App"
|
import History from "../components/History"
|
||||||
import {useState} from "preact/hooks"
|
import Dashboard from "../components/Dashboard"
|
||||||
import {Navbar} from "../components/Navbar"
|
import TrainsetManagement from "../components/TrainsetManagement"
|
||||||
import {Main} from "../components/Main"
|
import TestsetManagement from "../components/TestsetManagement"
|
||||||
import {Footer} from "../components/Footer"
|
import { Footer } from "../components/Footer"
|
||||||
import '../styles/base.sass'
|
import '../styles/base.sass'
|
||||||
|
import '../styles/history.sass'
|
||||||
|
import '../styles/pagination.sass'
|
||||||
|
import '../styles/dashboard.sass'
|
||||||
|
|
||||||
|
|
||||||
export function App(props: any) {
|
export function App(props: any) {
|
||||||
const [resultText, setResultText] = useState("Please enter your name below 👇");
|
|
||||||
const [name, setName] = useState('');
|
|
||||||
const updateName = (e: any) => setName(e.target.value);
|
|
||||||
const updateResultText = (result: string) => setResultText(result);
|
|
||||||
|
|
||||||
const greet = async() => {
|
|
||||||
const result = await (window as any).go.main.App.Greet("World")
|
|
||||||
console.log('result', result)
|
|
||||||
|
|
||||||
Greet(name).then(updateResultText);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="App">
|
<div id="App">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<Main />
|
<Router>
|
||||||
|
<Route path="/" component={Main} />
|
||||||
|
<Route path="/dashboard" component={Dashboard} />
|
||||||
|
<Route path="/history" component={History} />
|
||||||
|
<Route path="/dashboard/datasets" component={TrainsetManagement} />
|
||||||
|
<Route path="/dashboard/testsets" component={TestsetManagement} />
|
||||||
|
</Router>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
html {
|
|
||||||
background-color: rgba(27, 38, 54, 1);
|
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
color: white;
|
|
||||||
font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
|
|
||||||
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
|
||||||
sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: "Nunito";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
src: local(""),
|
|
||||||
url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
height: 100vh;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,159 @@
|
|||||||
|
html
|
||||||
|
text-align: center
|
||||||
|
color: white
|
||||||
|
|
||||||
|
body
|
||||||
|
margin: 0
|
||||||
|
color: white
|
||||||
|
font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI"
|
||||||
|
|
||||||
|
@font-face
|
||||||
|
font-family: "Nunito"
|
||||||
|
font-style: normal
|
||||||
|
font-weight: 400
|
||||||
|
src: local(""),url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2")
|
||||||
|
|
||||||
|
@font-face
|
||||||
|
font-family: "ZcoolHappy"
|
||||||
|
src: url("../assets/fonts/站酷快乐体.ttf") format("truetype")
|
||||||
|
|
||||||
|
:root
|
||||||
|
--primary: #3B82F6
|
||||||
|
|
||||||
#app
|
#app
|
||||||
height: 100vh
|
height: 100vh
|
||||||
text-align: center
|
text-align: center
|
||||||
background-color: #f8fafc
|
background-color: #F8FAFC
|
||||||
|
|
||||||
|
.app-navbar
|
||||||
|
width: calc(100% - 2rem)
|
||||||
|
position: fixed
|
||||||
|
margin: 1rem 1rem 0 1rem
|
||||||
|
z-index: 50
|
||||||
|
|
||||||
|
.navbar-container
|
||||||
|
display: inline-flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: space-between
|
||||||
|
width: 100%
|
||||||
|
margin: 0 auto
|
||||||
|
padding: 0.6rem 1.2rem
|
||||||
|
background-color: #FFFFFF
|
||||||
|
backdrop-filter: blur(8px)
|
||||||
|
border-radius: 0.6rem
|
||||||
|
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 var(--border)
|
||||||
|
|
||||||
|
.container-left
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
gap: 0.75rem
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.icon
|
||||||
|
width: 2rem
|
||||||
|
height: 2rem
|
||||||
|
color: var(--primary)
|
||||||
|
|
||||||
|
.container-right
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: space-between
|
||||||
|
|
||||||
|
> a
|
||||||
|
display: flex
|
||||||
|
padding: 0 1.5rem
|
||||||
|
color: #7D91B2
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
color: var(--primary)
|
||||||
|
|
||||||
|
> button
|
||||||
|
width: 7rem
|
||||||
|
height: 2.6rem
|
||||||
|
margin-left: 1.5rem
|
||||||
|
color: #FFFFFF
|
||||||
|
background-color: var(--primary)
|
||||||
|
border-radius: 0.3rem
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.app-main
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
height: 648px
|
||||||
|
padding: 7rem 1rem 4rem 1rem
|
||||||
|
|
||||||
|
.main-container
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
width: 42rem
|
||||||
|
margin: 0 auto
|
||||||
|
|
||||||
|
.title
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
text-align: center
|
||||||
|
margin-bottom: 2rem
|
||||||
|
|
||||||
|
> h1
|
||||||
|
font-family: "ZcoolHappy"
|
||||||
|
font-weight: 700
|
||||||
|
font-size: 2.75rem
|
||||||
|
margin-bottom: 0.75rem
|
||||||
|
color: #323232
|
||||||
|
|
||||||
|
> span
|
||||||
|
color: var(--primary)
|
||||||
|
|
||||||
|
> p
|
||||||
|
text-align: center
|
||||||
|
color: #5D5D5D
|
||||||
|
font-size: 1.0625rem
|
||||||
|
margin-bottom: 1rem
|
||||||
|
max-width: 42rem
|
||||||
|
|
||||||
|
> span
|
||||||
|
font-weight: bold
|
||||||
|
color: var(--primary)
|
||||||
|
|
||||||
|
> i
|
||||||
|
font-style: normal
|
||||||
|
text-align: center
|
||||||
|
color: #FFD572
|
||||||
|
font-size: 0.75rem
|
||||||
|
margin: 0 auto
|
||||||
|
padding: 0.25rem 0.75rem
|
||||||
|
background-color: #38383D
|
||||||
|
border-radius: 0.2rem
|
||||||
|
|
||||||
|
.upload
|
||||||
|
width: 36rem
|
||||||
|
margin: 0 auto 3rem auto
|
||||||
|
|
||||||
|
.upload-zone
|
||||||
|
background-color: white
|
||||||
|
border-radius: 1.5rem
|
||||||
|
border-width: 2px
|
||||||
|
border: 2px dashed #c6c6c6
|
||||||
|
padding: 3rem
|
||||||
|
text-align: center
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.app-footer
|
||||||
|
display: flex
|
||||||
|
justify-content: center
|
||||||
|
position: fixed
|
||||||
|
width: 100vw
|
||||||
|
height: 5rem
|
||||||
|
background-color: #131313
|
||||||
|
padding: 2rem 1rem
|
||||||
|
bottom: 0
|
||||||
|
|
||||||
|
> span
|
||||||
|
color: #595959
|
||||||
|
font-size: 0.8rem
|
||||||
|
margin: 0 0.5rem
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce)
|
@media (prefers-reduced-motion: reduce)
|
||||||
.animate-fade-in,
|
.animate-fade-in,
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
.app-dashboard
|
||||||
|
display: flex
|
||||||
|
height: 648px
|
||||||
|
padding: 7rem 1rem 4rem 1rem
|
||||||
|
|
||||||
|
.dashboard-sidebar
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
align-items: center
|
||||||
|
width: 20%
|
||||||
|
height: 100%
|
||||||
|
border-right: 1px solid #9AAAC6
|
||||||
|
|
||||||
|
> a
|
||||||
|
display: inline-flex
|
||||||
|
height: 2.5rem
|
||||||
|
line-height: 2.5rem
|
||||||
|
color: #8E8E8E
|
||||||
|
border-bottom: 1px solid #9AAAC6
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.dashboard-content
|
||||||
|
width: 80%
|
||||||
|
height: 100%
|
||||||
|
// background-color: #555
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
.app-history
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
align-items: center
|
||||||
|
height: 651px
|
||||||
|
padding: 7rem 1rem 4rem 1rem
|
||||||
|
|
||||||
|
.history-card
|
||||||
|
display: flex
|
||||||
|
justify-content: space-between
|
||||||
|
width: calc(100% - 20rem)
|
||||||
|
height: 5rem
|
||||||
|
padding: 1rem
|
||||||
|
margin-bottom: 0.6rem
|
||||||
|
background-color: #FFFFFF
|
||||||
|
backdrop-filter: blur(8px)
|
||||||
|
border-radius: 0.6rem
|
||||||
|
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 var(--border)
|
||||||
|
|
||||||
|
.card-left
|
||||||
|
width: 3rem
|
||||||
|
height: 3rem
|
||||||
|
background-color: #333333
|
||||||
|
|
||||||
|
.card-right
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
width: calc(100% - 5rem)
|
||||||
|
height: 5rem
|
||||||
|
|
||||||
|
.right-top
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: space-between
|
||||||
|
|
||||||
|
> h3
|
||||||
|
color: #333333
|
||||||
|
font-size: 1rem
|
||||||
|
font-weight: bold
|
||||||
|
|
||||||
|
> span
|
||||||
|
color: #cccccc
|
||||||
|
font-size: 0.8rem
|
||||||
|
|
||||||
|
.right-overview
|
||||||
|
width: 100%
|
||||||
|
margin-top: 0.25rem
|
||||||
|
color: #cccccc
|
||||||
|
font-size: 0.9rem
|
||||||
|
text-align: left
|
||||||
|
|
||||||
|
.history-pagination
|
||||||
|
width: calc(100% - 20rem)
|
||||||
|
margin-top: 1rem
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
.div-pagination
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
justify-content: flex-end
|
||||||
|
width: 100%
|
||||||
|
height: 30px
|
||||||
|
|
||||||
|
|
||||||
|
.div-pagination-core
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
width: auto
|
||||||
|
height: 30px
|
||||||
|
img
|
||||||
|
width: 10px
|
||||||
|
height: 10px
|
||||||
|
|
||||||
|
span
|
||||||
|
height: 30px
|
||||||
|
line-height: 30px
|
||||||
|
font-size: 14px
|
||||||
|
color: #333333
|
||||||
|
|
||||||
|
.pagination-icon
|
||||||
|
height: 100%
|
||||||
|
margin-left: 10px
|
||||||
|
cursor: pointer
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
justify-content: center
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
.pagination-icon:first-child
|
||||||
|
margin-right: 10px
|
||||||
|
|
||||||
|
.pagination-num
|
||||||
|
width: auto
|
||||||
|
min-width: 20px
|
||||||
|
height: 30px
|
||||||
|
color: #202020
|
||||||
|
font-size: 12px
|
||||||
|
font-weight: 800
|
||||||
|
text-align: center
|
||||||
|
border-radius: 6px
|
||||||
|
padding: 0 4px
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.pagination-num-selected
|
||||||
|
color: #c53048
|
||||||
|
font-weight: 800
|
||||||
|
|
||||||
|
.pagination-etc
|
||||||
|
width: 30px
|
||||||
|
height: 30px
|
||||||
|
color: #333333
|
||||||
|
font-weight: 800
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
.pagination-word
|
||||||
|
font-size: 12px
|
||||||
|
margin: 0 5px 0 5px
|
||||||
|
color: #202020
|
||||||
|
|
||||||
|
input
|
||||||
|
width: 20px
|
||||||
|
height: 20px
|
||||||
|
color: #292929
|
||||||
|
// background-color: $transcript-bg
|
||||||
|
font-size: 12px
|
||||||
|
text-align: center
|
||||||
|
border: 1px solid #DDDFE6
|
||||||
|
border-radius: 4px
|
||||||
|
margin-top: 2px
|
||||||
|
|
||||||
|
input:focus
|
||||||
|
outline: none
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
"esModuleInterop": false,
|
"esModuleInterop": false,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": false,
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user