refactor(ops): add ops web scaffold and update router for split dirs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f9f9915012
commit
797e96cbb5
|
|
@ -3,14 +3,30 @@ use tower_http::services::ServeDir;
|
|||
|
||||
use crate::app::AppState;
|
||||
|
||||
const WEB_ROOT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/web");
|
||||
async fn no_cache(
|
||||
req: axum::extract::Request,
|
||||
next: axum::middleware::Next,
|
||||
) -> axum::response::Response {
|
||||
let mut response = next.run(req).await;
|
||||
response.headers_mut().insert(
|
||||
axum::http::header::CACHE_CONTROL,
|
||||
axum::http::HeaderValue::from_static("no-store"),
|
||||
);
|
||||
response
|
||||
}
|
||||
|
||||
pub fn build_router(state: AppState) -> Router {
|
||||
Router::new()
|
||||
.route("/api/health", get(health_check))
|
||||
.nest_service(
|
||||
.nest(
|
||||
"/ui",
|
||||
ServeDir::new(WEB_ROOT).append_index_html_on_directories(true),
|
||||
Router::new()
|
||||
.fallback_service(
|
||||
ServeDir::new("web/ops")
|
||||
.append_index_html_on_directories(true)
|
||||
.fallback(ServeDir::new("web/core")),
|
||||
)
|
||||
.layer(axum::middleware::from_fn(no_cache)),
|
||||
)
|
||||
.with_state(state)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>PLC Control Operation System</title>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>Operation System</h1>
|
||||
<p>This web root is a placeholder for the operation-system app skeleton.</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<header class="topbar">
|
||||
<div class="title">运转系统</div>
|
||||
<div class="topbar-actions">
|
||||
<div class="status" id="statusText">
|
||||
<span class="ws-dot" id="wsDot"></span>
|
||||
<span id="wsLabel">连接中…</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>运转系统</title>
|
||||
<link rel="stylesheet" href="/ui/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div data-partial="/ui/html/topbar.html"></div>
|
||||
|
||||
<main>
|
||||
<div class="muted" style="padding:2rem;text-align:center">运转系统页面开发中</div>
|
||||
</main>
|
||||
|
||||
<script type="module" src="/ui/js/index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
function bootstrap() {
|
||||
console.log("Operation system app initialized");
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
async function loadPartial(slot) {
|
||||
const response = await fetch(slot.dataset.partial);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to load partial: ${slot.dataset.partial}`);
|
||||
}
|
||||
|
||||
const html = await response.text();
|
||||
slot.insertAdjacentHTML("beforebegin", html);
|
||||
slot.remove();
|
||||
}
|
||||
|
||||
async function bootstrapPage() {
|
||||
const slots = Array.from(document.querySelectorAll("[data-partial]"));
|
||||
await Promise.all(slots.map((slot) => loadPartial(slot)));
|
||||
await import("./app.js");
|
||||
}
|
||||
|
||||
bootstrapPage().catch((error) => {
|
||||
document.body.innerHTML = `<pre>${error.message || String(error)}</pre>`;
|
||||
});
|
||||
Loading…
Reference in New Issue