feat: OpsxDB 桌面数据库客户端首版入库
含工作台/连库多引擎字段与 SSH·SSL、结果编辑、Redis 键浏览、 Tauri 桌面与 docs/落地页;排除本地构建产物与 sidecar 二进制。
This commit is contained in:
commit
f8740d27f7
240 files changed
+21625
No files matched your search
@@ -0,0 +1,92 @@
|
||||
import { useWorkspaceStore } from "./store";
|
||||
|
||||
export function SchemaPane() {
|
||||
const schema = useWorkspaceStore((s) => s.schemaView);
|
||||
const set = useWorkspaceStore((s) => s.set);
|
||||
|
||||
if (!schema) {
|
||||
return (
|
||||
<div className="ops-empty" style={{ minHeight: 120 }}>
|
||||
<h2 style={{ fontSize: "var(--ops-font-sm)" }}>表结构</h2>
|
||||
<p>在对象树点表,或右键「查看结构」。</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.loading) {
|
||||
return (
|
||||
<div className="px-3 py-2 text-[12.5px]" style={{ color: "var(--ops-muted)" }}>
|
||||
加载 {schema.table} 结构…
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.error) {
|
||||
return (
|
||||
<div
|
||||
className="m-1.5 rounded border px-2.5 py-1.5 text-[12.5px]"
|
||||
style={{
|
||||
borderColor: "color-mix(in srgb, var(--ops-danger) 40%, var(--ops-border))",
|
||||
background: "color-mix(in srgb, var(--ops-danger) 10%, transparent)",
|
||||
color: "var(--ops-danger)",
|
||||
}}
|
||||
>
|
||||
{schema.error}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-0 flex-1 flex-col">
|
||||
<div className="ops-section-label justify-between border-b">
|
||||
<span>
|
||||
结构 · {schema.database ? `${schema.database}.` : ""}
|
||||
{schema.table}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
className="normal-case tracking-normal hover:underline"
|
||||
style={{ color: "var(--ops-accent)" }}
|
||||
onClick={() => set("resultTab", "data")}
|
||||
>
|
||||
回结果
|
||||
</button>
|
||||
</div>
|
||||
<div className="min-h-0 flex-1 overflow-auto">
|
||||
{schema.columns.length === 0 ? (
|
||||
<div className="px-3 py-2 text-[12.5px]" style={{ color: "var(--ops-muted)" }}>
|
||||
无列信息
|
||||
</div>
|
||||
) : (
|
||||
<table className="ops-grid" style={{ width: "100%" }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{ width: 36 }}>#</th>
|
||||
<th>列名</th>
|
||||
<th>类型</th>
|
||||
<th style={{ width: 64 }}>可空</th>
|
||||
<th>默认值</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{schema.columns.map((c, i) => (
|
||||
<tr key={c.name}>
|
||||
<td className="ops-rownum">{i + 1}</td>
|
||||
<td>
|
||||
{c.key === "PRI" ? <span title="主键">🔑 </span> : null}
|
||||
{c.name}
|
||||
</td>
|
||||
<td className="font-mono text-[12px]">{c.type}</td>
|
||||
<td>{c.nullable ? "YES" : "NO"}</td>
|
||||
<td className="font-mono text-[12px]" style={{ color: "var(--ops-muted)" }}>
|
||||
{c.default == null ? <span className="ops-null">NULL</span> : String(c.default)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user