Files
laser-data-hub/templates/dashboard.html
T
broccoliandClaude Fable 5 edfb216561 激光材料数据平台 1.3.0
公开数据看板、四位 Key 录入面板、管理后台与三级权限、动态字段配置、
PostgreSQL/SQLite 双支持、数据库备份,以及本版新增的成品图上传与预览。

图片相关:
- 录入表单支持相册选图与手机端直接拍照,每条记录最多 6 张
- 浏览器内压缩到最长边 1600 并剥离 EXIF,入库统一为 JPG/PNG
- 二进制直接入库,现有备份自动覆盖图片,部署无需新增卷
- 详情页缩略图宫格与全屏 lightbox,公开看板同样可见

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 22:06:02 +08:00

59 lines
8.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>{{ app_name }}</title><link rel="stylesheet" href="/static/app.css"></head>
<body class="app-body" data-role="{{ user.role }}" data-csrf="{{ csrf_token }}">
<aside class="sidebar" id="sidebar">
<div class="logo"><div class="brand-mark">L</div><div><strong>LASER DATA</strong><span>材料数据管理平台</span></div></div>
<nav>
<button class="nav-item active" data-view="overview"><i></i><span>数据概览</span></button>
{% if user.role in ['admin','uploader'] %}<button class="nav-item" data-view="entry"><i></i><span>手动录入</span></button>{% endif %}
<button class="nav-item" data-view="records"><i></i><span>数据中心</span></button>
{% if user.role == 'admin' %}
<p class="nav-label">系统管理</p>
<button class="nav-item" data-view="fields"><i></i><span>数据字段配置</span></button>
<button class="nav-item" data-view="users"><i></i><span>用户与权限</span></button>
<button class="nav-item" data-view="backup"><i></i><span>备份管理</span></button>
<button class="nav-item" data-view="audit"><i></i><span>审计日志</span></button>
{% endif %}
</nav>
<div class="side-help"><b>需要帮助?</b><span>查看操作手册和接口文档</span><div><a href="/docs" target="_blank">API 文档</a><a href="https://github.com" hidden>文档</a></div></div>
<div class="side-user"><div class="avatar">{{ user.display_name[0] }}</div><div><b>{{ user.display_name }}</b><span>{{ {'admin':'系统管理员','uploader':'数据录入员','viewer':'只读访客'}[user.role] }}</span></div><button id="logoutBtn" title="退出"></button></div>
</aside>
<div class="mobile-bar"><button id="menuBtn"></button><div class="logo"><div class="brand-mark">L</div><strong>LASER DATA</strong></div><div class="avatar">{{ user.display_name[0] }}</div></div>
<main class="content">
<header class="topbar"><div><p class="eyebrow">MATERIAL INTELLIGENCE</p><h1 id="pageTitle">数据概览</h1></div><div class="top-actions"><span class="status-dot">系统运行正常</span><a class="ghost button-link" href="/" target="_blank">公开看板</a>{% if user.role in ['admin','uploader'] %}<button class="ghost" id="entryKeyBtn">录入 Key</button>{% endif %}<button class="ghost" id="passwordBtn">修改密码</button></div></header>
<section class="view active" id="view-overview">
{% if user.must_change_password %}<div class="notice"><b>首次登录请修改初始密码</b><span>完成密码更新后,此提示将自动消失。</span><button id="noticePasswordBtn">立即修改</button></div>{% endif %}
<div class="hero-card"><div><p class="eyebrow">GOOD DATA, BETTER DECISIONS</p><h2>下午好,{{ user.display_name }}</h2><p>每一组可靠的数据,都让下一次雕刻更接近理想结果。</p></div>{% if user.role in ['admin','uploader'] %}<button class="light-button" data-go="entry">录入新数据 <span></span></button>{% endif %}</div>
<div class="metric-grid">
<article class="metric"><span class="metric-icon coral"></span><div><p>数据总量</p><strong>{{ counts.records }}</strong><small>条实验记录</small></div></article>
<article class="metric"><span class="metric-icon blue"></span><div><p>录入次数</p><strong>{{ counts.batches }}</strong><small>次成功保存</small></div></article>
<article class="metric"><span class="metric-icon green"></span><div><p>活跃用户</p><strong>{{ counts.users }}</strong><small>个有效账号</small></div></article>
</div>
<div class="panel-grid"><section class="panel"><div class="panel-head"><div><p class="eyebrow">RECENT ENTRIES</p><h3>最近录入</h3></div><button class="text-button" data-go="records">查看全部 →</button></div><div id="recentRecords" class="loading">正在加载…</div></section>
<section class="panel quick-panel"><p class="eyebrow">QUICK START</p><h3>规范录入三步走</h3><ol><li><b>填写材料身份</b><span>实验 ID 必须唯一</span></li><li><b>补充参数与结果</b><span>标记“可选”的物性字段可留空</span></li><li><b>校验并保存</b><span>系统自动检查格式并记录操作者</span></li></ol></section></div>
</section>
<section class="view" id="view-entry">
<div class="section-intro"><div><h2 id="entryTitle">手动录入实验数据</h2><p><span class="required-star">*</span> 为必填;标记“可选”的字段可留空。</p></div><button class="secondary" id="resetRecordBtn" type="button">清空表单</button></div>
<form id="recordForm" class="record-form">
<input type="hidden" id="recordId">
{% include "_record_fields.html" %}
<div class="form-actions"><span>保存后可在数据中心继续编辑</span><button class="primary" id="saveRecordBtn" type="submit">保存实验数据</button></div>
</form>
</section>
<section class="view" id="view-records"><div class="section-intro"><div><h2>数据中心</h2><p>按实验 ID、材料名称或分类快速查找、编辑和管理实验记录。</p></div>{% if user.role in ['admin','uploader'] %}<button class="primary" data-go="entry"> 新建记录</button>{% endif %}</div><section class="panel"><div class="filters"><input id="recordSearch" placeholder="搜索实验 ID 或材料名称"><input id="categorySearch" placeholder="材料分类(精确)"><button class="primary" id="searchBtn">查询</button></div><div class="table-wrap"><table><thead><tr><th>实验 ID</th><th>测试日期</th><th>材料</th><th>厚度</th><th>功率</th><th>速度</th><th>切透</th><th>清晰度</th><th>操作</th></tr></thead><tbody id="recordRows"></tbody></table></div><div class="pager" id="recordPager"></div></section></section>
{% if user.role == 'admin' %}
<section class="view" id="view-fields"><div class="section-intro"><div><h2>数据字段配置</h2><p>添加扩展数据种类,设置输入形式、必填规则和公开性;历史值不会因配置修改而删除。</p></div><button class="primary" id="newFieldBtn"> 添加数据字段</button></div><section class="panel"><div class="table-wrap"><table><thead><tr><th>字段名称</th><th>填写形式</th><th>规则</th><th>公开</th><th>状态</th><th>已有值</th><th>排序</th><th></th></tr></thead><tbody id="fieldRows"></tbody></table></div></section></section>
<section class="view" id="view-users"><div class="section-intro"><div><h2>用户与权限</h2><p>管理员负责账号创建、角色分配、停用与密码重置。</p></div><button class="primary" id="newUserBtn"> 新建用户</button></div><section class="panel"><div class="table-wrap"><table><thead><tr><th>用户</th><th>用户名</th><th>角色</th><th>状态</th><th>创建时间</th><th></th></tr></thead><tbody id="userRows"></tbody></table></div></section></section>
<section class="view" id="view-backup"><div class="section-intro"><div><h2>备份管理</h2><p>支持 SQLite 在线一致性备份与 PostgreSQL pg_dump,默认保留 30 天。</p></div><button class="primary" id="backupBtn">⟳ 立即备份</button></div><section class="panel"><div class="table-wrap"><table><thead><tr><th>文件名</th><th>数据库</th><th>大小</th><th>创建人</th><th>创建时间</th><th>SHA-256</th><th></th></tr></thead><tbody id="backupRows"></tbody></table></div></section></section>
<section class="view" id="view-audit"><div class="section-intro"><div><h2>审计日志</h2><p>记录登录、录入、修改、删除、账号及备份等关键动作。</p></div></div><section class="panel"><div class="table-wrap"><table><thead><tr><th>时间</th><th>操作者</th><th>动作</th><th>资源</th><th>IP 地址</th><th>详情</th></tr></thead><tbody id="auditRows"></tbody></table></div></section></section>
{% endif %}
</main>
<div class="modal" id="modal" hidden><div class="modal-backdrop"></div><div class="modal-card"><button class="modal-close" data-close>×</button><div id="modalContent"></div></div></div>
<div class="toast-stack" id="toasts"></div>
<script>window.APP={csrf:document.body.dataset.csrf,role:document.body.dataset.role,mustChange:{{ 'true' if user.must_change_password else 'false' }},entryKeyConfigured:{{ 'true' if user.entry_key_hash else 'false' }}};</script><script src="/static/dynamic-fields.js"></script><script src="/static/image-viewer.js"></script><script src="/static/image-upload.js"></script><script src="/static/app.js"></script>
</body></html>