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,50 @@
|
||||
:root {
|
||||
--bg: #0e1116;
|
||||
--panel: #151a21;
|
||||
--border: #243044;
|
||||
--text: #e6edf7;
|
||||
--muted: #8b9bb4;
|
||||
--accent: #3b82f6;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font: 14px/1.55 ui-sans-serif, system-ui, -apple-system, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
}
|
||||
.nav { border-bottom: 1px solid var(--border); background: var(--panel); }
|
||||
.nav .inner {
|
||||
max-width: 880px; margin: 0 auto; padding: 0 20px; height: 48px;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
}
|
||||
.brand { display: flex; align-items: center; gap: 10px; color: var(--text); text-decoration: none; font-weight: 600; }
|
||||
.logo {
|
||||
width: 28px; height: 28px; border-radius: 7px; background: var(--accent);
|
||||
display: grid; place-items: center; font-size: 11px; font-weight: 700; color: #fff;
|
||||
}
|
||||
.nav a { color: var(--muted); text-decoration: none; margin-left: 16px; font-size: 13px; }
|
||||
.nav a:hover { color: var(--text); }
|
||||
.hero { max-width: 880px; margin: 0 auto; padding: 56px 20px 72px; }
|
||||
.eyebrow { color: var(--accent); font-size: 12px; letter-spacing: .04em; margin: 0 0 12px; }
|
||||
h1 { font-size: 28px; line-height: 1.25; margin: 0 0 14px; font-weight: 650; }
|
||||
.lead { color: var(--muted); max-width: 52ch; margin: 0 0 24px; }
|
||||
.actions { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 36px; }
|
||||
.btn {
|
||||
display: inline-flex; align-items: center; height: 36px; padding: 0 14px;
|
||||
border-radius: 8px; text-decoration: none; font-size: 13px; font-weight: 550;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
|
||||
.btn.ghost { color: var(--text); background: transparent; }
|
||||
.caps { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; }
|
||||
.caps li {
|
||||
background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
|
||||
padding: 12px 14px; display: grid; gap: 4px;
|
||||
}
|
||||
.caps strong { font-size: 13px; }
|
||||
.caps span { color: var(--muted); font-size: 12.5px; }
|
||||
.foot {
|
||||
border-top: 1px solid var(--border); color: var(--muted);
|
||||
text-align: center; padding: 18px; font-size: 12px;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Package site:产品官网落地页(嵌入二进制,深色密度跟工作台)。
|
||||
package site
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//go:embed template.html assets
|
||||
var files embed.FS
|
||||
|
||||
type Handler struct {
|
||||
html string
|
||||
}
|
||||
|
||||
func New() *Handler {
|
||||
raw, err := files.ReadFile("template.html")
|
||||
if err != nil {
|
||||
panic("site: template.html 缺失: " + err.Error())
|
||||
}
|
||||
return &Handler{html: string(raw)}
|
||||
}
|
||||
|
||||
func (h *Handler) Register(r *gin.Engine) {
|
||||
r.GET("/", h.Page)
|
||||
r.GET("/home", h.Page)
|
||||
r.GET("/index.html", h.Page)
|
||||
r.GET("/site/assets/*file", h.Asset)
|
||||
}
|
||||
|
||||
func (h *Handler) Page(c *gin.Context) {
|
||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||
c.Header("Cache-Control", "no-cache")
|
||||
_, _ = c.Writer.WriteString(h.html)
|
||||
}
|
||||
|
||||
func (h *Handler) Asset(c *gin.Context) {
|
||||
name := strings.TrimPrefix(c.Param("file"), "/")
|
||||
if strings.Contains(name, "..") {
|
||||
c.Status(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
data, err := files.ReadFile("assets/" + name)
|
||||
if err != nil {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
ct := "application/octet-stream"
|
||||
if strings.HasSuffix(name, ".css") {
|
||||
ct = "text/css; charset=utf-8"
|
||||
}
|
||||
c.Header("Content-Type", ct)
|
||||
c.Header("Cache-Control", "public, max-age=3600")
|
||||
c.Data(http.StatusOK, ct, data)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>OpsxDB — 本地优先的桌面数据库工作台</title>
|
||||
<meta name="description" content="OpsxDB 主交付是桌面 GUI:连库、写 SQL、看结果。开发态 Vite 仅调试用。">
|
||||
<link rel="stylesheet" href="/site/assets/site.css">
|
||||
</head>
|
||||
<body>
|
||||
<header class="nav">
|
||||
<div class="inner">
|
||||
<a class="brand" href="/home"><span class="logo">DB</span> OpsxDB</a>
|
||||
<nav>
|
||||
<a href="/docs">文档</a>
|
||||
<a href="#download">下载</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main class="hero">
|
||||
<p class="eyebrow">桌面 GUI · 本地优先</p>
|
||||
<h1>连库、写 SQL、看结果——都在本机完成</h1>
|
||||
<p class="lead">正式形态是可安装的桌面应用,本地后端随应用启动。浏览器里的 :5174 只是开发壳,不是产品。</p>
|
||||
<div class="actions">
|
||||
<a class="btn primary" id="download" href="#download">下载桌面版(占位)</a>
|
||||
<a class="btn ghost" href="/docs">阅读文档</a>
|
||||
</div>
|
||||
<ul class="caps">
|
||||
<li><strong>多驱动连库</strong><span>MySQL / Postgres / SQLite 等,会话保活</span></li>
|
||||
<li><strong>工作台密度</strong><span>结果集、对象树、书签,深色紧凑布局</span></li>
|
||||
<li><strong>本机后端</strong><span>双击启动即带本地服务,不依赖手动起 Vite</span></li>
|
||||
</ul>
|
||||
</main>
|
||||
<footer class="foot">© 2026 OpsxDB · 产品形态为桌面 GUI</footer>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user