WFreeCAD / index.html
HelloSun's picture
Polish responsive UI, fix gear bore, compact error overlay
5a083bc verified
Raw History Blame Contribute Delete
7.6 kB
<!doctype html>
<html lang="zh-Hant">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WFreeCAD · tiny part studio</title>
<meta name="description" content="A tiny in-browser FreeCAD Python playground. Load a Part macro and orbit the result.">
<link rel="icon" href="favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="vendor/codemirror/codemirror.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="topbar">
<a class="brand" href="./" aria-label="WFreeCAD 首頁">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round">
<circle cx="12" cy="12" r="3.1"/>
<path d="M12 3v2.6M12 18.4V21M3 12h2.6M18.4 12H21M5.6 5.6l1.9 1.9M16.5 16.5l1.9 1.9M18.4 5.6l-1.9 1.9M7.5 16.5l-1.9 1.9"/>
</svg>
</span>
<span class="brand-name">WFreeCAD</span>
<span class="brand-sub">part studio</span>
</a>
<div class="topbar-actions">
<div class="runtime" id="runtime" data-state="idle" title="Python 執行環境">
<span class="runtime-dot" aria-hidden="true"></span>
<span class="runtime-text" id="runtimeText">Python 待命</span>
</div>
<button class="btn ghost" id="loadBtn" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 16V4m0 0L7.5 8.5M12 4l4.5 4.5M5 15.5v3A1.5 1.5 0 0 0 6.5 20h11a1.5 1.5 0 0 0 1.5-1.5v-3"/>
</svg>
載入 .py
</button>
<input type="file" id="fileInput" accept=".py,.txt,text/x-python" hidden>
</div>
</header>
<main class="workspace">
<aside class="panel examples" aria-label="範例">
<div class="panel-head">
<h2>範例</h2>
<span class="panel-count" id="exampleCount">04</span>
</div>
<div class="example-list" id="exampleList">
<div class="example-skeleton"></div>
<div class="example-skeleton"></div>
<div class="example-skeleton"></div>
</div>
<div class="examples-foot">
<span class="drop-dot"></span>
拖放 .py 到畫布也可以載入
</div>
</aside>
<section class="panel editor-panel" aria-label="Python 編輯器">
<div class="panel-head">
<div class="file-meta">
<span class="file-dot" aria-hidden="true"></span>
<span class="file-name" id="fileName">未命名.py</span>
<span class="state-pill" id="fileState" data-state="example">範例</span>
</div>
<div class="editor-actions">
<button class="icon-btn" id="revertBtn" type="button" title="回到範例程式" aria-label="回到範例程式" disabled>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4.5 10.5a7.5 7.5 0 1 1 2.1 5.3M4.5 10.5V5.5m0 5h5"/>
</svg>
</button>
<button class="btn run" id="runBtn" type="button" title="執行 (Ctrl / ⌘ + Enter)">
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M8.5 5.4v13.2L19 12 8.5 5.4Z"/>
</svg>
執行
<kbd>⌘↵</kbd>
</button>
</div>
</div>
<div class="editor-wrap" id="editorWrap">
<textarea id="editor" spellcheck="false" aria-label="Python 程式碼"></textarea>
</div>
<div class="editor-status">
<span class="status-left"><span class="lang-dot"></span>Python · FreeCAD Part API</span>
<span class="status-right" id="cursorInfo">Ln 1, Col 1</span>
</div>
</section>
<section class="panel preview-panel" aria-label="3D 預覽畫布">
<div class="panel-head">
<div class="preview-meta">
<span class="live-dot" aria-hidden="true"></span>
<h2>預覽</h2>
<span class="object-count" id="objectCount">0 個物件</span>
</div>
<div class="view-actions">
<button class="icon-btn is-on" id="autoBtn" type="button" title="自動旋轉" aria-label="自動旋轉" aria-pressed="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M20 10.5a8 8 0 0 0-14.6-3M4 13.5a8 8 0 0 0 14.6 3M4 4.5v4h4M20 19.5v-4h-4"/>
</svg>
</button>
<button class="icon-btn" id="resetBtn" type="button" title="重設視角" aria-label="重設視角">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="m12 3 8 4.5v9L12 21l-8-4.5v-9L12 3Z"/>
<path d="m4 7.5 8 4.5 8-4.5M12 12v9"/>
</svg>
</button>
</div>
</div>
<div class="canvas-wrap" id="canvasWrap">
<canvas id="view" aria-label="3D 模型預覽"></canvas>
<div class="canvas-hint" id="canvasHint">
<span class="mouse-icon" aria-hidden="true"></span>
拖曳旋轉 · 滾輪縮放
</div>
<div class="canvas-loading" id="loadingState" hidden>
<span class="spinner" aria-hidden="true"></span>
<div>
<strong>正在執行 Python</strong>
<span id="loadingText">首次執行會下載執行環境…</span>
</div>
</div>
<div class="canvas-empty" id="emptyState" hidden>
<span class="empty-mark" aria-hidden="true">∅</span>
<strong>沒有可顯示的物件</strong>
<span id="emptyHint">在程式裡呼叫 <code>Part.show(shape)</code></span>
</div>
<div class="canvas-error" id="errorState" hidden>
<div class="error-card">
<div class="error-head">
<span>無法執行這段程式</span>
<button class="icon-btn tiny" id="dismissError" type="button" aria-label="關閉錯誤">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" aria-hidden="true">
<path d="m6 6 12 12M18 6 6 18"/>
</svg>
</button>
</div>
<pre id="errorText"></pre>
<p>支援 FreeCAD / Part 的基本 Part API。</p>
</div>
</div>
<div class="toast" id="toast" role="status" aria-live="polite" hidden></div>
</div>
</section>
</main>
<div class="drop-overlay" id="dropOverlay" hidden>
<div class="drop-card">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 16V4m0 0L7.5 8.5M12 4l4.5 4.5M5 15.5v3A1.5 1.5 0 0 0 6.5 20h11a1.5 1.5 0 0 0 1.5-1.5v-3"/>
</svg>
<strong>放開以載入 .py</strong>
<span>檔案會直接開啟在編輯器</span>
</div>
</div>
<script src="vendor/codemirror/codemirror.js"></script>
<script src="vendor/codemirror/python.js"></script>
<script src="vendor/codemirror/closebrackets.js"></script>
<script src="vendor/codemirror/matchbrackets.js"></script>
<script src="vendor/codemirror/active-line.js"></script>
<script type="module" src="app.js"></script>
</body>
</html>