mirror of
https://github.com/ClovertaTheTrilobita/cellpose-web.git
synced 2026-04-01 23:14:50 +00:00
feature(frontend): 前端将从后端动态获取模型列表
This commit is contained in:
parent
de44004e37
commit
f55b2cc4d7
2 changed files with 65 additions and 11 deletions
|
|
@ -25,6 +25,7 @@ cfg.data.root_dir = str((CONFIG_PATH.parent / cfg.data.root_dir).resolve())
|
||||||
BASE_DIR = cfg.data.root_dir
|
BASE_DIR = cfg.data.root_dir
|
||||||
UPLOAD_DIR = cfg.data.upload_dir
|
UPLOAD_DIR = cfg.data.upload_dir
|
||||||
OUTPUT_DIR = cfg.data.run.output_dir
|
OUTPUT_DIR = cfg.data.run.output_dir
|
||||||
|
MODELS_DIR = str((CONFIG_PATH.parent / cfg.model.save_dir).resolve())
|
||||||
|
|
||||||
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
||||||
executor = ThreadPoolExecutor(max_workers=4)
|
executor = ThreadPoolExecutor(max_workers=4)
|
||||||
|
|
@ -160,3 +161,8 @@ def preview():
|
||||||
})
|
})
|
||||||
|
|
||||||
return jsonify({"ok": True, "count": len(result), "images": result})
|
return jsonify({"ok": True, "count": len(result), "images": result})
|
||||||
|
|
||||||
|
@app.get("/models")
|
||||||
|
def list_models():
|
||||||
|
models_list = os.listdir(MODELS_DIR)
|
||||||
|
return jsonify({"ok": True, "models": models_list})
|
||||||
|
|
@ -22,27 +22,21 @@
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<span class="input-group-text">flow threshold:</span>
|
<span class="input-group-text">flow threshold:</span>
|
||||||
<input id="flow" type="text" class="form-control" placeholder="" />
|
<input id="flow" type="text" class="form-control" placeholder="" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<span class="input-group-text">cellprob threshold:</span>
|
<span class="input-group-text">cellprob threshold:</span>
|
||||||
<input id="cellprob" type="text" class="form-control" placeholder="" />
|
<input id="cellprob" type="text" class="form-control" placeholder="" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
|
|
||||||
<span class="input-group-text">diameter:</span>
|
<span class="input-group-text">diameter:</span>
|
||||||
<input id="diameter" type="text" class="form-control" placeholder="" />
|
<input id="diameter" type="text" class="form-control" placeholder="" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
<select id="model" class="form-select">
|
<select id="model" class="form-select"></select>
|
||||||
<option value="cpsam">模型(下拉单选):</option>
|
</label>
|
||||||
<option value="cpsam">cpsam</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -64,7 +58,61 @@
|
||||||
integrity="sha384-ep+dxp/oz2RKF89ALMPGc7Z89QFa32C8Uv1A3TcEK8sMzXVysblLA3+eJWTzPJzT"
|
integrity="sha384-ep+dxp/oz2RKF89ALMPGc7Z89QFa32C8Uv1A3TcEK8sMzXVysblLA3+eJWTzPJzT"
|
||||||
crossorigin="anonymous"></script>
|
crossorigin="anonymous"></script>
|
||||||
<script>
|
<script>
|
||||||
const API = "http://10.147.18.141:5000/upload";
|
const API = "http://10.147.18.141:5000/";
|
||||||
|
const APT_UPLOAD = API + "upload";
|
||||||
|
const API_MODEL = API + "models";
|
||||||
|
|
||||||
|
async function loadModels() {
|
||||||
|
const select = document.getElementById('model');
|
||||||
|
// 占位 & 禁用,避免用户在加载中点选
|
||||||
|
select.disabled = true;
|
||||||
|
select.innerHTML = '<option value="">加载中…</option>';
|
||||||
|
|
||||||
|
// 可选:超时控制(5 秒)
|
||||||
|
const controller = new AbortController();
|
||||||
|
const t = setTimeout(() => controller.abort(), 5000);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resp = await fetch(API_MODEL, {
|
||||||
|
headers: { 'Accept': 'application/json' },
|
||||||
|
signal: controller.signal
|
||||||
|
});
|
||||||
|
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
||||||
|
|
||||||
|
const data = await resp.json();
|
||||||
|
const list = Array.isArray(data.models) ? data.models : [];
|
||||||
|
|
||||||
|
// 记住之前的选择(如果有)
|
||||||
|
const prev = select.value;
|
||||||
|
|
||||||
|
// 重新渲染选项
|
||||||
|
select.innerHTML = '<option value="" disabled selected>请选择模型</option>';
|
||||||
|
const seen = new Set();
|
||||||
|
for (const name of list) {
|
||||||
|
if (!name || seen.has(name)) continue;
|
||||||
|
seen.add(name);
|
||||||
|
const opt = document.createElement('option');
|
||||||
|
opt.value = String(name);
|
||||||
|
opt.textContent = String(name);
|
||||||
|
select.appendChild(opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果原选择仍然存在,则恢复它
|
||||||
|
if (prev && seen.has(prev)) {
|
||||||
|
select.value = prev;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('加载模型列表失败:', err);
|
||||||
|
select.innerHTML = '<option value="">加载失败(点击重试)</option>';
|
||||||
|
// 点击下拉框时重试
|
||||||
|
select.addEventListener('click', loadModels, { once: true });
|
||||||
|
} finally {
|
||||||
|
clearTimeout(t);
|
||||||
|
select.disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', loadModels);
|
||||||
|
|
||||||
function buildUrl() {
|
function buildUrl() {
|
||||||
// 获取参数
|
// 获取参数
|
||||||
|
|
@ -81,7 +129,7 @@
|
||||||
diameter: diameter
|
diameter: diameter
|
||||||
});
|
});
|
||||||
|
|
||||||
return `${API}?${qs.toString()}`;
|
return `${API_UPLOAD}?${qs.toString()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("uploadBtn").addEventListener("click", async () => {
|
document.getElementById("uploadBtn").addEventListener("click", async () => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue