mirror of
https://github.com/ClovertaTheTrilobita/cellpose-web.git
synced 2026-04-01 23:14:50 +00:00
feat(backend): 新增更多接口
feat(frontend): 前端样式优化
This commit is contained in:
parent
8ca5f971ba
commit
723bfdf2d9
6 changed files with 653 additions and 73 deletions
|
|
@ -5,6 +5,8 @@ import redis
|
|||
import datetime
|
||||
import json
|
||||
|
||||
from sympy import false
|
||||
|
||||
CONFIG_PATH = Path(__file__).parent / "config.yaml"
|
||||
cfg = OmegaConf.load(CONFIG_PATH)
|
||||
cfg.data.root_dir = str((CONFIG_PATH.parent / cfg.data.root_dir).resolve())
|
||||
|
|
@ -38,7 +40,21 @@ class Cptrain:
|
|||
model_name: str | None = None,
|
||||
image_filter: str = "_img",
|
||||
mask_filter: str = "_masks",
|
||||
base_model: str = "cpsam"):
|
||||
base_model: str = "cpsam",
|
||||
train_probs: list[float] = None,
|
||||
test_probs: list[float] = None,
|
||||
batch_size: int = 8,
|
||||
learning_rate = 5e-5,
|
||||
n_epochs: int = 100,
|
||||
weight_decay=0.1,
|
||||
normalize: bool =True,
|
||||
compute_flows: bool = False,
|
||||
min_train_masks: int = 5,
|
||||
nimg_per_epoch: int =None,
|
||||
rescale: bool= False,
|
||||
scale_range=None,
|
||||
channel_axis: int = None,
|
||||
):
|
||||
|
||||
train_dir = Path(TRAIN_DIR) / time
|
||||
test_dir = Path(TEST_DIR) / time
|
||||
|
|
@ -56,9 +72,13 @@ class Cptrain:
|
|||
model_path, train_losses, test_losses = train.train_seg(model.net,
|
||||
train_data=images, train_labels=labels,
|
||||
test_data=test_images, test_labels=test_labels,
|
||||
weight_decay=0.1, learning_rate=1e-5,
|
||||
n_epochs=100, model_name=model_name,
|
||||
save_path=BASE_DIR)
|
||||
train_probs=train_probs, test_probs=test_probs,
|
||||
weight_decay=weight_decay, learning_rate=learning_rate,
|
||||
n_epochs=n_epochs, model_name=model_name,
|
||||
save_path=BASE_DIR, batch_size=batch_size,
|
||||
normalize=normalize, compute_flows=compute_flows, min_train_masks=min_train_masks,
|
||||
nimg_per_epoch=nimg_per_epoch, rescale=rescale, scale_range=scale_range, channel_axis=channel_axis
|
||||
)
|
||||
|
||||
set_status(time, "done", train_losses, test_losses)
|
||||
print("模型已保存到:", model_path)
|
||||
|
|
|
|||
|
|
@ -145,6 +145,17 @@ def train_upload():
|
|||
image_filter = request.args.get("image_filter") or "_img"
|
||||
mask_filter = request.args.get("mask_filter") or "_masks"
|
||||
base_model = request.args.get("base_model") or "cpsam"
|
||||
batch_size = request.args.get("batch_size") or 8
|
||||
learning_rate = request.args.get("learning_rate") or 5e-5
|
||||
n_epochs = request.args.get("n_epochs") or 100
|
||||
weight_decay = request.args.get("weight_decay") or 0.1
|
||||
normalize = request.args.get("normalize") or True
|
||||
compute_flows = request.args.get("compute_flows") or False
|
||||
min_train_masks = request.args.get(" min_train_masks") or 5
|
||||
nimg_per_epoch = request.args.get("nimg_per_epoch") or None
|
||||
rescale = request.args.get("rescale") or False
|
||||
scale_range = request.args.get("scale_range") or None
|
||||
channel_axis = request.args.get("channel_axis") or None
|
||||
|
||||
train_files = request.files.getlist("train_files")
|
||||
test_files = request.files.getlist("test_files")
|
||||
|
|
@ -172,7 +183,18 @@ def train_upload():
|
|||
model_name=model_name,
|
||||
image_filter=image_filter,
|
||||
mask_filter=mask_filter,
|
||||
base_model=base_model
|
||||
base_model=base_model,
|
||||
batch_size=batch_size,
|
||||
learning_rate=learning_rate,
|
||||
n_epochs=n_epochs,
|
||||
weight_decay=weight_decay,
|
||||
normalize=normalize,
|
||||
compute_flows=compute_flows,
|
||||
min_train_masks=min_train_masks,
|
||||
nimg_per_epoch=nimg_per_epoch,
|
||||
rescale=rescale,
|
||||
scale_range=scale_range,
|
||||
channel_axis=channel_axis,
|
||||
))
|
||||
|
||||
fut = executor.submit(job)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,139 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="zh-CN" data-bs-theme="auto">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Bootstrap demo</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>任务面板</title>
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous" />
|
||||
<!-- Bootstrap Icons -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
/* 背景渐变 + 玻璃感卡片 */
|
||||
body {
|
||||
min-height: 100vh;
|
||||
background: radial-gradient(1200px 600px at 20% 10%, rgba(13,110,253,.15), transparent 60%),
|
||||
radial-gradient(800px 400px at 80% 90%, rgba(32,201,151,.18), transparent 60%),
|
||||
linear-gradient(180deg, #f8f9fa, #eef2f7);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: radial-gradient(1200px 600px at 20% 10%, rgba(13,110,253,.25), transparent 60%),
|
||||
radial-gradient(800px 400px at 80% 90%, rgba(32,201,151,.25), transparent 60%),
|
||||
linear-gradient(180deg, #0b1020, #0e1326);
|
||||
}
|
||||
}
|
||||
|
||||
.glass-card {
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.65);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
[data-bs-theme="dark"] .glass-card {
|
||||
background: rgba(17, 20, 34, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
transition: transform .15s ease, box-shadow .15s ease;
|
||||
padding: 1.1rem 1.4rem;
|
||||
font-size: 1.05rem;
|
||||
border-radius: 1rem;
|
||||
}
|
||||
.action-btn:hover, .action-btn:focus-visible {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 0.75rem 1.25rem rgba(0,0,0,.12);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .6rem;
|
||||
}
|
||||
|
||||
.brand-badge {
|
||||
letter-spacing: .08em;
|
||||
background: rgba(13,110,253,.1);
|
||||
color: #0d6efd;
|
||||
border: 1px solid rgba(13,110,253,.15);
|
||||
}
|
||||
[data-bs-theme="dark"] .brand-badge {
|
||||
background: rgba(13,110,253,.15);
|
||||
color: #9ec5fe;
|
||||
border-color: rgba(13,110,253,.25);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main class="container min-vh-100 d-flex align-items-center justify-content-center py-5">
|
||||
<div class="col-12 col-md-10 col-lg-8">
|
||||
<div class="glass-card rounded-4 shadow-lg p-4 p-md-5 text-center">
|
||||
<div class="d-flex justify-content-center mb-3">
|
||||
<span class="badge brand-badge rounded-pill px-3 py-2">
|
||||
<i class="bi bi-rocket-takeoff me-1"></i> Cell Processing
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<a href="run.html">运行</a>
|
||||
<a href="train.html">训练</a>
|
||||
<h1 class="display-6 fw-semibold mb-2">欢迎使用任务面板</h1>
|
||||
<p class="text-secondary mb-4">
|
||||
选择你要进行的操作。可随时返回此页切换任务。
|
||||
</p>
|
||||
|
||||
<div class="row g-3 g-md-4 justify-content-center">
|
||||
<div class="col-12 col-sm-6">
|
||||
<a href="run.html" class="btn btn-primary w-100 action-btn btn-icon" role="button" aria-label="进入运行页面">
|
||||
<i class="bi bi-play-circle-fill fs-4"></i>
|
||||
<span>
|
||||
运行<br>
|
||||
<small class="opacity-75">快速执行已有模型/流程</small>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<a href="train.html" class="btn btn-outline-primary w-100 action-btn btn-icon" role="button" aria-label="进入训练页面">
|
||||
<i class="bi bi-cpu-fill fs-4"></i>
|
||||
<span>
|
||||
训练<br>
|
||||
<small class="opacity-75">启动或继续训练任务</small>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4 my-md-5">
|
||||
|
||||
<div class="d-flex flex-column flex-md-row gap-2 justify-content-center">
|
||||
<a href="#" class="link-secondary text-decoration-none">
|
||||
<i class="bi bi-book"></i> 文档
|
||||
</a>
|
||||
<span class="text-secondary d-none d-md-inline">•</span>
|
||||
<a href="#" class="link-secondary text-decoration-none">
|
||||
<i class="bi bi-gear"></i> 设置
|
||||
</a>
|
||||
<span class="text-secondary d-none d-md-inline">•</span>
|
||||
<span class="text-secondary"><i class="bi bi-keyboard"></i> 快捷键:<kbd>R</kbd> 运行,<kbd>T</kbd> 训练</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 键盘快捷键(可选) -->
|
||||
<script>
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (['INPUT','TEXTAREA'].includes((e.target.tagName || '').toUpperCase())) return;
|
||||
if (e.key.toLowerCase() === 'r') location.href = 'run.html';
|
||||
if (e.key.toLowerCase() === 't') location.href = 'train.html';
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- 只需引入 bundle(已包含 Popper) -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
|
||||
crossorigin="anonymous"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -1,9 +1,148 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="UTF-8" />
|
||||
<h1>运行结果预览</h1>
|
||||
<p id="none-exist" hidden></p>
|
||||
<div id="gallery"></div>
|
||||
<button onclick="downloadTif()">下载tif</button>
|
||||
<html lang="zh-CN" data-bs-theme="auto">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>运行结果预览</title>
|
||||
|
||||
<!-- Bootstrap + Icons(与前页保持一致) -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
/* 背景与玻璃卡片 —— 与首页一致 */
|
||||
body {
|
||||
min-height: 100vh;
|
||||
background: radial-gradient(1200px 600px at 20% 10%, rgba(13,110,253,.15), transparent 60%),
|
||||
radial-gradient(800px 400px at 80% 90%, rgba(32,201,151,.18), transparent 60%),
|
||||
linear-gradient(180deg, #f8f9fa, #eef2f7);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: radial-gradient(1200px 600px at 20% 10%, rgba(13,110,253,.25), transparent 60%),
|
||||
radial-gradient(800px 400px at 80% 90%, rgba(32,201,151,.25), transparent 60%),
|
||||
linear-gradient(180deg, #0b1020, #0e1326);
|
||||
}
|
||||
}
|
||||
.glass-card {
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.65);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
[data-bs-theme="dark"] .glass-card {
|
||||
background: rgba(17, 20, 34, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
/* 标题区 */
|
||||
.page-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .6rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.sub-hint {
|
||||
font-size: .9rem;
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
/* 预览网格:仅美化 #gallery,保持 id 不变 */
|
||||
#gallery {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
/* 预览卡片 */
|
||||
.thumb {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 1rem;
|
||||
background: rgba(0,0,0,.05);
|
||||
border: 1px solid rgba(0,0,0,.06);
|
||||
transition: transform .12s ease, box-shadow .12s ease;
|
||||
}
|
||||
.thumb:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 .9rem 1.2rem rgba(0,0,0,.12);
|
||||
}
|
||||
.thumb img, .thumb canvas, .thumb video {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
.thumb .badge-overlay {
|
||||
position: absolute;
|
||||
top: .5rem;
|
||||
left: .5rem;
|
||||
padding: .25rem .5rem;
|
||||
border-radius: .5rem;
|
||||
background: rgba(13,110,253,.85);
|
||||
color: #fff;
|
||||
font-size: .75rem;
|
||||
}
|
||||
|
||||
/* 空态提示:仅美化 #none-exist */
|
||||
#none-exist {
|
||||
margin: 0;
|
||||
padding: 1rem 1.25rem;
|
||||
border-radius: .75rem;
|
||||
background: rgba(108,117,125,.08);
|
||||
border: 1px dashed rgba(108,117,125,.35);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* 下载按钮 */
|
||||
.download-wrap {
|
||||
gap: .75rem;
|
||||
}
|
||||
.download-btn {
|
||||
padding: .65rem 1.1rem;
|
||||
border-radius: .8rem;
|
||||
transition: transform .12s ease, box-shadow .12s ease;
|
||||
}
|
||||
.download-btn:hover, .download-btn:focus-visible {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 .75rem 1.25rem rgba(0,0,0,.12);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container py-4">
|
||||
<div class="glass-card rounded-4 shadow-lg p-4 p-md-5">
|
||||
<!-- 标题区(保持语义,未改 id) -->
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-3">
|
||||
<h1 class="page-title h4">
|
||||
<i class="bi bi-images"></i> 运行结果预览
|
||||
</h1>
|
||||
<div class="sub-hint">
|
||||
生成的图像/掩膜将显示在下方网格中
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空态提示:仅样式增强,不改 id/hidden 机制 -->
|
||||
<p id="none-exist" hidden></p>
|
||||
|
||||
<!-- 预览网格:只美化 #gallery -->
|
||||
<div id="gallery"></div>
|
||||
|
||||
<!-- 下载按钮:保留 onclick,不动逻辑,只加样式 -->
|
||||
<div class="mt-4 d-flex download-wrap">
|
||||
<button class="btn btn-primary d-inline-flex align-items-center download-btn"
|
||||
onclick="downloadTif()">
|
||||
<i class="bi bi-download me-2"></i> 下载 TIF
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 仅需引入 bundle(如你已有可省略) -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
<script src="api.js"></script>
|
||||
|
|
@ -67,3 +206,5 @@
|
|||
document.body.removeChild(a);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
<div style="padding: 1rem 1rem;">
|
||||
<!-- <div style="padding: 1rem 1rem;">
|
||||
<div class="mb-3 border" style="padding: 1rem 1rem;">
|
||||
<div class="input-group mb-3">
|
||||
<input id="fileInput" type="file" class="form-control" multiple />
|
||||
|
|
@ -47,7 +47,94 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br><br><br>
|
||||
<br><br><br> -->
|
||||
|
||||
<div class="container py-4">
|
||||
<div class="glass-card rounded-4 shadow-lg p-4 p-md-5">
|
||||
|
||||
<!-- 上传区 -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<h2 class="h5 section-title mb-0"><i class="bi bi-folder2-open me-2"></i>选择文件</h2>
|
||||
<span class="hint">可多选</span>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-cloud-arrow-up"></i></span>
|
||||
<input id="fileInput" type="file" class="form-control" multiple />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<!-- 参数区 -->
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-lg-8">
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-speedometer2 me-1"></i>flow threshold</span>
|
||||
<input id="flow" type="text" class="form-control" placeholder="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-bezier2 me-1"></i>cellprob threshold</span>
|
||||
<input id="cellprob" type="text" class="form-control" placeholder="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-bounding-box-circles me-1"></i>diameter</span>
|
||||
<input id="diameter" type="text" class="form-control" placeholder="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="w-100">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-cpu-fill me-1"></i>model</span>
|
||||
<select id="model" class="form-select"></select>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧说明(可删) -->
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="p-3 rounded-3 border h-100">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="bi bi-info-circle me-2"></i>
|
||||
<strong>提示</strong>
|
||||
</div>
|
||||
<div class="hint">
|
||||
• 参数留空将使用默认值。<br>
|
||||
• 数值可使用小数(如 0.4)。<br>
|
||||
• 选择合适的模型以获得更稳健的分割效果。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 行动区 -->
|
||||
<div class="mt-4 d-flex flex-column flex-md-row align-items-stretch gap-3">
|
||||
<button id="uploadBtn" class="btn btn-success d-inline-flex align-items-center">
|
||||
<i class="bi bi-upload me-2"></i> Upload
|
||||
</button>
|
||||
|
||||
<div class="flex-grow-1">
|
||||
<div class="d-flex align-items-center justify-content-between mb-1">
|
||||
<span class="hint"><i class="bi bi-activity me-1"></i>进度</span>
|
||||
<span class="hint" id="barText"></span><!-- 如需,你的 JS 可写入文本 -->
|
||||
</div>
|
||||
<progress id="bar" max="100" value="0"></progress>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
|
|
@ -184,6 +271,82 @@
|
|||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* 页面背景与卡片 */
|
||||
body {
|
||||
min-height: 100vh;
|
||||
background: radial-gradient(1200px 600px at 20% 10%, rgba(13,110,253,.15), transparent 60%),
|
||||
radial-gradient(800px 400px at 80% 90%, rgba(32,201,151,.18), transparent 60%),
|
||||
linear-gradient(180deg, #f8f9fa, #eef2f7);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: radial-gradient(1200px 600px at 20% 10%, rgba(13,110,253,.25), transparent 60%),
|
||||
radial-gradient(800px 400px at 80% 90%, rgba(32,201,151,.25), transparent 60%),
|
||||
linear-gradient(180deg, #0b1020, #0e1326);
|
||||
}
|
||||
}
|
||||
.glass-card {
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.65);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
[data-bs-theme="dark"] .glass-card {
|
||||
background: rgba(17, 20, 34, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
/* 区块与控件 */
|
||||
.section-title {
|
||||
font-weight: 600;
|
||||
letter-spacing: .02em;
|
||||
}
|
||||
.input-group-text i {
|
||||
opacity: .7;
|
||||
}
|
||||
.hint {
|
||||
font-size: .875rem;
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
/* 原生 <progress> 美化(保持 id 不变) */
|
||||
#bar {
|
||||
width: 100%;
|
||||
height: 1rem;
|
||||
border: none;
|
||||
border-radius: .75rem;
|
||||
background-color: rgba(13,110,253,.15);
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* Chrome / Edge / Safari */
|
||||
#bar::-webkit-progress-bar {
|
||||
background-color: transparent;
|
||||
}
|
||||
#bar::-webkit-progress-value {
|
||||
background: linear-gradient(90deg, #0d6efd, #6ea8fe);
|
||||
border-radius: .75rem;
|
||||
}
|
||||
/* Firefox */
|
||||
#bar::-moz-progress-bar {
|
||||
background: linear-gradient(90deg, #0d6efd, #6ea8fe);
|
||||
border-radius: .75rem;
|
||||
}
|
||||
|
||||
/* 上传按钮动效 */
|
||||
#uploadBtn {
|
||||
padding: .65rem 1.1rem;
|
||||
border-radius: .8rem;
|
||||
transition: transform .12s ease, box-shadow .12s ease;
|
||||
}
|
||||
#uploadBtn:hover, #uploadBtn:focus-visible {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 .75rem 1.25rem rgba(0,0,0,.12);
|
||||
}
|
||||
</style>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -1,58 +1,171 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<html lang="zh-CN" data-bs-theme="auto">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Bootstrap demo</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
|
||||
<title>训练任务</title>
|
||||
|
||||
<!-- Bootstrap 5.3 与 Icons(与前页一致) -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
/* 背景与玻璃卡片 —— 与首页/预览页一致 */
|
||||
body{
|
||||
min-height:100vh;
|
||||
background: radial-gradient(1200px 600px at 20% 10%, rgba(13,110,253,.15), transparent 60%),
|
||||
radial-gradient(800px 400px at 80% 90%, rgba(32,201,151,.18), transparent 60%),
|
||||
linear-gradient(180deg, #f8f9fa, #eef2f7);
|
||||
}
|
||||
@media (prefers-color-scheme: dark){
|
||||
body{
|
||||
background: radial-gradient(1200px 600px at 20% 10%, rgba(13,110,253,.25), transparent 60%),
|
||||
radial-gradient(800px 400px at 80% 90%, rgba(32,201,151,.25), transparent 60%),
|
||||
linear-gradient(180deg, #0b1020, #0e1326);
|
||||
}
|
||||
}
|
||||
.glass-card{
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
background: rgba(255,255,255,.65);
|
||||
border:1px solid rgba(255,255,255,.5);
|
||||
}
|
||||
[data-bs-theme="dark"] .glass-card{
|
||||
background: rgba(17,20,34,.6);
|
||||
border:1px solid rgba(255,255,255,.08);
|
||||
}
|
||||
|
||||
.section-title{
|
||||
display:flex; align-items:center; gap:.6rem;
|
||||
margin-bottom:0;
|
||||
}
|
||||
.hint{font-size:.9rem; opacity:.75}
|
||||
|
||||
/* 原生 progress 美化(保持 id 不变) */
|
||||
#bar{
|
||||
width:100%; height:1rem; border:none; border-radius:.75rem;
|
||||
background-color:rgba(13,110,253,.15); overflow:hidden; vertical-align:middle;
|
||||
}
|
||||
#bar::-webkit-progress-bar{background:transparent}
|
||||
#bar::-webkit-progress-value{background:linear-gradient(90deg,#0d6efd,#6ea8fe); border-radius:.75rem}
|
||||
#bar::-moz-progress-bar{background:linear-gradient(90deg,#0d6efd,#6ea8fe); border-radius:.75rem}
|
||||
|
||||
/* 上传按钮动效(保持 id 不变) */
|
||||
#uploadBtn{
|
||||
padding:.65rem 1.1rem; border-radius:.8rem;
|
||||
transition:transform .12s ease, box-shadow .12s ease;
|
||||
}
|
||||
#uploadBtn:hover, #uploadBtn:focus-visible{
|
||||
transform:translateY(-1px);
|
||||
box-shadow:0 .75rem 1.25rem rgba(0,0,0,.12);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="padding: 1rem 1rem;">
|
||||
<div class="mb-3 border" style="padding: 1rem 1rem;">
|
||||
<div class="input-group mb-3">
|
||||
<h5>选择训练文件</h5>
|
||||
<div class="container py-4">
|
||||
<div class="glass-card rounded-4 shadow-lg p-4 p-md-5">
|
||||
<!-- 标题 -->
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-3">
|
||||
<h1 class="section-title h4"><i class="bi bi-cpu"></i> 训练配置</h1>
|
||||
<div class="hint">选择训练/测试数据并设置模型参数</div>
|
||||
</div>
|
||||
|
||||
<!-- 选择文件 -->
|
||||
<div class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-lg-6">
|
||||
<label class="form-label fw-semibold"><i class="bi bi-folder2-open me-1"></i>选择训练文件</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-cloud-arrow-up"></i></span>
|
||||
<input id="trainFileInput" type="file" class="form-control" multiple />
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<h5>选择测试文件</h5>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6">
|
||||
<label class="form-label fw-semibold"><i class="bi bi-folder2 me-1"></i>选择测试文件</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-cloud-arrow-up"></i></span>
|
||||
<input id="testFileInput" type="file" class="form-control" multiple />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div>
|
||||
<div style="padding-right: 50rem;">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text">model name:</span>
|
||||
<hr class="my-4">
|
||||
|
||||
<!-- 参数区(仅美化,不改 id) -->
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-lg-8">
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-type me-1"></i>model name</span>
|
||||
<input id="name" type="text" class="form-control" placeholder="为你的模型命名" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text">image filter:</span>
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-image me-1"></i>image filter</span>
|
||||
<input id="image_filter" type="text" class="form-control" placeholder="_img" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text">masks filter</span>
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-brush me-1"></i>masks filter</span>
|
||||
<input id="masks_filter" type="text" class="form-control" placeholder="_masks" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label>
|
||||
<div class="col-12">
|
||||
<label class="w-100">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-cpu-fill me-1"></i>model</span>
|
||||
<select id="model" class="form-select"></select>
|
||||
</label>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<button id="uploadBtn" class="btn btn-success">Upload</button>
|
||||
<progress id="bar" max="100" value="0" style="width:300px;"></progress>
|
||||
</div>
|
||||
|
||||
<!-- 右侧提示(可删,不影响逻辑) -->
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="p-3 rounded-3 border h-100">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="bi bi-info-circle me-2"></i><strong>提示</strong>
|
||||
</div>
|
||||
<div class="hint">
|
||||
• 名称用于区分训练产物(日志/权重)。<br>
|
||||
• filter 用于匹配文件名,如 <code>*_img.png</code>、<code>*_masks.png</code>。<br>
|
||||
• 选择合适的预训练模型可加速收敛。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br><br><br>
|
||||
</div>
|
||||
|
||||
<!-- 行动与进度(保持 id 与机制不变) -->
|
||||
<div class="mt-4 d-flex flex-column flex-md-row align-items-stretch gap-3">
|
||||
<button id="uploadBtn" class="btn btn-success d-inline-flex align-items-center">
|
||||
<i class="bi bi-play-circle me-2"></i> Upload
|
||||
</button>
|
||||
<div class="flex-grow-1">
|
||||
<div class="d-flex align-items-center justify-content-between mb-1">
|
||||
<span class="hint"><i class="bi bi-activity me-1"></i>进度</span>
|
||||
<span class="hint" id="barText"></span><!-- 如需 JS 写入文字可用;不用也不影响 -->
|
||||
</div>
|
||||
<progress id="bar" max="100" value="0"></progress>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 只需引入 bundle(含 Popper) -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue