Skip to content

Ferramentas de produtividade

O SkylerX conecta ações de 30 segundos a 30 minutos do dia a dia de DBA / backend a teclado / paleta de comandos / notificações — objetivo: menos cliques, menos janelas. Esta página segue a ordem do "mais usado", e cada item tem fato e arquivo correspondente.

1. Visão geral

FerramentaEntradaResolve
Paleta de comandos ⌘KGlobal / Settings → AtalhosAcessa tudo sem navegar menus
Busca global de objetos ⌘⇧OGlobalFuzzy de tabelas / views / colunas → localiza na árvore
Snippets SQLDrawer à direita / botão Reusa queries com
HistóricoDrawer à direitaPor tempo / duração, slow em vermelho
Favoritos⌘K → "Favoritos" / ToolbarTabelas / views / queries de acesso rápido
Atalhos customSettings → Atalhos12 comandos com remap + detecção de conflito
Dashboard⌘K → "Dashboard"Múltiplos SQLs em cards "como o sistema está hoje"
Notificações webhookSettings → NotificaçõesDingTalk / Lark / Slack / genérico para slow query + erros
Multi-janelas ⌘⇧NFile → Nova janelaMesma app, duas sessões independentes

2. Paleta de comandos ⌘K

Local: packages/ui/src/components/CommandPalette.vue + packages/ui/src/Workspace.vue (rota).

⌘K (mac) / Ctrl+K (Win/Linux) → caixa flutuante no topo → digite para filtrar → ↑↓ → Enter executa. Esc fecha.

Busca

ts
const filtered = computed(() => {
  const q = query.value.trim().toLowerCase()
  return q
    ? props.items.filter((it) => `${it.label} ${it.hint ?? ''}`.toLowerCase().includes(q))
    : props.items
})
  • Casa label + hint (hint da conexão = nome do dialeto), pure substring includes (sem pinyin / fuzzy ordenado — velocidade > flexibilidade)
  • Máx 50 entradas (evitar lentidão)

Ações nativas

Tabela das paletteItems em Workspace.vue (ações + por-conexão + conexões):

ID globalLabelEquivalente
act:new-connNova conexãoToolbar +
act:object-searchBusca global de objetos⌘⇧O
act:schema-diffSchema diffTools → Schema diff
act:data-diffData diffTools → Data diff
act:privilegesPrivilégiosClique direito → Privilégios
act:settingsSettings⌘,
act:export-conns / act:import-connsImportar / exportar configMenu File
act:refreshAtualizar árvoreF5
act:favoritesFavoritosToolbar ⭐
act:oplogLog de operaçõesToolbar
act:monitorMonitorToolbar
act:dashboardDashboardTools → Dashboard
act:ndjson-viewerVisualizador NDJSONToolbar
act:contractsData ContractsTools → Data Contracts
act:o2dmOracle → DMToolbar
act:mig-assessAvaliação de migração (perfilamento da origem + notas + conversão IA + exportação)Clique direito numa conexão Oracle/DM
act:translateSQL translateToolbar
act:notifWebhooksSettings → Notificações
act:keybindAtalhosSettings → Atalhos
act:driftSchema driftToolbar
act:ai-chat / act:ai / act:ai-toolboxChat IA / Assistente / Toolbox⌘⇧L
act:about / act:shortcutsSobre / AtalhosMenu Help
act:new-windowNova janela (apenas desktop)⌘⇧N

Ações por conexão

Expandidas por conexão; label sufixada com · nome · dialeto:

Prefixo IDSignificado
act:activity:Atividade (processlist / pg_stat_activity)
act:obtopo:Topologia OB (só OB)
act:snapshots: / act:backup:Snapshots / Backup
act:health: / act:vqd:Health check / Visual query
act:slowq: / act:idxrec: / act:repl:Slow query / Index recommender / Replication lag
act:compliance: / act:search-value:Conformidade / Cross-table search
act:aicmt:IA escrever comentários
conn:Abrir conexão (grupo = "Conexões")

Um workspace com 5 conexões mostra 80+ entradas; o filter substring + grupo encontra em 3-4 chars.

Extensão

A lógica concentra-se em paletteItems. Adicionar comando: array { id, label, group } + roteamento em onPaletteSelect() (else if). Para "por conexão", siga act:compliance:: .map(c => ({ id: \act:xxx:${c.id}`, ... })), e no router item.id.startsWith()`.


3. Busca global de objetos ⌘⇧O

Local: packages/ui/src/components/ObjectSearchDialog.vue.

⌘⇧O / Ctrl+Shift+O → abre o diálogo, busca fuzzy de tabelas/views/colunas entre bancos da conexão.

SQL de busca

information_schema, duas variantes:

FamíliaSchemas excluídosEscape
MySQLmysql / information_schema / performance_schema / sysLIKE '%term%', %_\\ 3-char
PGpg_catalog / information_schemaILIKE '%term%'
OutrosNão suportado, indica busca manual

Top 100 por categoria (tabela / view / coluna); debounce 280ms.

Comportamento

  • Click = reveal: emite reveal; Workspace localiza e seleciona na árvore (expande os caminhos)
  • Hover mostra "Preview": emite preview → abre SELECT * FROM schema.table LIMIT 200 (quote por dialeto)
  • Ícones: tabela / view / · coluna

Concorrência segura

seq incremental; só o último resultado é commitado, evita override por respostas antigas.


4. Snippets SQL

Local: packages/ui/src/snippets.ts + packages/ui/src/components/SnippetsPanel.vue.

Estrutura

ts
interface Snippet {
  id: string        // `${timestamp}-${rand5}`
  name: string      // nome do usuário; default = 40 chars do SQL
  sql: string
  tags?: string[]   // tags para filtro
  dialects?: DbDialect[]  // restrição de dialeto, vazio = universal
  createdAt: number
}

localStorage.skylerx.snippets, Vue reactive + watch deep.

Adicionar / remover

  • Qualquer editor SQL: clique direito → "Salvar como snippet" ou
  • Histórico: por linha
  • Settings → Editor → Salvar snippet default ⌘S (configurável)

Templates com placeholders

em snippets → prompt na inserção:

sql
SELECT * FROM {{table}} WHERE id = {{id}}

applySnippetVars() extrai na ordem; qualquer cancel → não insere.

Filtro por dialeto

snippetsForDialect(dialect) filtra:

  • dialects = [] ou ausente → universal
  • dialects = [MySQL, MariaDB] → só em conexões MySQL / MariaDB

Evita ver SQLs MySQL em conexões PG.

Painel

AçãoEfeito
BuscaSubstring sobre name + SQL + tags
Click em #xxxFiltra por tag; clique de novo cancela
Duplo cliqueAplica placeholders e insere
×Remove (sem confirmação)

5. Histórico

Local: packages/ui/src/components/HistoryPanel.vue.

Cada execução (sucesso / falha) grava em SQLite local: sql / executedAt / durationMs / success / pinned / tags / note.

Ordenação + filtros

ControleDescrição
BuscaSubstring em sql + tags + note
OrdenaçãoTempo desc (default) / Duração desc
≥ N msThreshold slow; linha vermelha (default 500ms)
📌Apenas fixados
LimparLimpa tudo

Fixados sempre no topo (pinned: 1); resto pela ordenação escolhida.

Ações por linha

BotãoEfeito
📌Fixar/desfixar
🏷Editar tags (csv: daily,prod,join)
📝Editar nota
Salvar como snippet (emite saveSnippet)
Duplo cliqueCarrega SQL no editor atual

Metadados via client.connections.historyMeta(id, patch) → SQLite (não localStorage).

Slow → notificação

Settings → Notificações → Trigger global → Slow query (ms) (settings.slowQueryNotifyMs). > 0 dispara notify('slow-query', ...) para os webhooks correspondentes.


6. Favoritos

Local: packages/ui/src/favorites.ts.

3 kind:

kindSignificadoClick
tableTabelaReveal + preview 200 linhas
viewViewIdem
querySQL customAbre em aba (atual / nova)

Chave primária

  • Objeto: ${connId}|${sqlName} — único por (conn, objeto); toggle remove
  • Query: q|${connId}|${createdAt}|${rand4} — múltiplas instâncias do mesmo SQL ("snapshots por momento")

Tags

setFavoriteTag(id, tag) atribui tag; painel agrupa.

Persistência

localStorage.skylerx.favorites, reactive + watch deep.

Do histórico para favoritos

addQueryFavorite({ connId, connName, dialect, name, sql, tags }) é o atalho "esta query vale guardar". do HistoryPanel → snippet; "Favoritar query atual" da toolbar → essa função.


7. Atalhos custom (K1)

Local: packages/ui/src/keybindings.ts + packages/ui/src/components/KeyBindingsDialog.vue.

Entrada: Settings → Atalhos / paleta → "Atalhos".

12 comandos

IDChord padrãoUso
run-sqlCmdOrCtrl+EnterExecutar SQL
paletteCmdOrCtrl+KPaleta
object-searchCmdOrCtrl+Shift+OBusca global
ai-chatCmdOrCtrl+Shift+LChat IA
new-connCmdOrCtrl+NNova conexão
new-queryCmdOrCtrl+TNova consulta
close-tabCmdOrCtrl+WFechar aba
findCmdOrCtrl+FBuscar no editor
replaceCmdOrCtrl+HSubstituir
format-sqlCmdOrCtrl+Shift+FFormatar SQL
save-snippetCmdOrCtrl+SSalvar snippet
settingsCmdOrCtrl+,Settings

Renderização

PlataformaCmdOrCtrl+Shift+K aparece como
macOS⌘⇧K (estilo nativo, sem +)
Windows / LinuxCtrl+Shift+K

Armazenado como CmdOrCtrl+... (independente de SO); render por formatChord().

Gravação

  1. Clique em "Gravar" → linha entra em modo gravação com input invisível (position: absolute; left: -9999px) para foco
  2. keydownchordFromEvent(e):
    • Modificadores em ordem fixa CmdOrCtrl → Shift → Alt
    • Letras únicas maiúsculas, space → Space, Enter / , / ArrowUp originais
    • Modificador puro → string vazia
  3. Enter salva / Esc cancela / Backspace em draft vazio = "desabilitar este comando" (string vazia)

Conflitos

conflicts computa colisões e mostra "conflito com XX" em vermelho.

Armazenamento + "restaurar default"

Só os diferentes do default em settings.keyBindings:

  • Voltar ao default → entrada removida
  • "Restaurar tudo" → limpa settings.keyBindings com confirmação
  • "Desabilitar" = string vazia (chave mantida)

8. Dashboard — multi-SQL multi-cards

Local: packages/ui/src/components/DashboardDialog.vue.

Entrada: Tools → Dashboard / ⌘K → "Dashboard".

Estrutura do card

ts
interface Card {
  id: string
  title: string
  connId: string
  sql: string
  lastRunAt?: number
  lastResult?: QueryResult | null
  lastError?: string | null
}
  • Persiste em localStorage.skylerx.dashboard.cards, sem lastResult (pode ser grande)
  • Exibe: título + conn + SQL (200 chars) + 5 linhas top de resultado (60 chars)

Ações

BotãoEfeito
+ Adicionar cardForm: título + conn + SQL (textarea 4 linhas)
↻ Atualizar tudoPromise.all(cards.map(runCard))
no cardAtualizar individual
Editar
×Remover (confirmação)

Não-funcionalidades

  • Sem auto-refresh: pode rodar em background esquecido; clique manual
  • Sem gráficos: "→ ChartDialog" é mais claro
  • Sem compartilhamento: pré-v0.5, sem dependência de cloud

9. Webhooks de notificação

Local: packages/ui/src/notifications.ts + packages/ui/src/components/NotificationSettingsDialog.vue.

Entrada: Settings → Notificações / ⌘K → "Webhooks".

4 canais

ChannelURLAssinatura
dingtalkDingTalk webhookHMAC-SHA256(ts\n${secret}, key=secret), query ?timestamp=&sign=urlencoded(...)
feishuLark webhookHMAC-SHA256(empty data, key=ts\n${secret}), sign no body
slackSlack incoming webhookSem assinatura (URL é credencial)
webhookPOST JSON genéricoSem assinatura, receptor decide

Assinatura via globalThis.crypto.subtle HMAC-SHA256, sem terceiros.

3 eventos

EventQuando
query-errorFalha SQL
slow-queryDuração ≥ settings.slowQueryNotifyMs (0 = off)
manualTeste / botão "Notificar"

Cada config pode subscrever independente (subscribe: NotifEvent[]).

Config

ts
interface NotifConfig {
  id: string
  name: string
  channel: 'dingtalk' | 'feishu' | 'slack' | 'webhook'
  webhookUrl: string
  secret?: string           // segredo DingTalk/Lark (opcional)
  enabled: boolean
  subscribe: NotifEvent[]
}

localStorage.skylerx.notifications, independente de settings (notificações têm volume e mudam muito).

Teste

Settings → Notificações → escolher config → "Testar". Condições:

  • enabled === true
  • webhookUrl não vazio
  • subscribe.includes('manual')

Falha → toast, não envia de verdade.

Não-bloqueante

notify(event, payload) é fire-and-forget:

ts
await Promise.all(targets.map(async (c) => {
  try { await dispatchOne(c, payload) }
  catch (e) { console.warn(`[notify] ${c.channel}/${c.name} failed:`, e) }
}))

Falha de webhook = warning no console. Notificação é canal auxiliar, não bloqueia fluxo principal.

Proxy fetch no desktop

Electron usa globalThis.api.ai.fetch (proxy do main, ignora CORS); web → fetch nativo.


10. Menu da aplicação

Local: apps/desktop/src/main/menu.ts.

7 menus (estilo DataGrip / Navicat):

MenuItens
SkylerX (mac)Sobre / Settings ⌘, / Verificar atualizações / Services / Esconder / Sair
FileNova conexão ⌘N / Nova query ⌘T / Abrir SQL ⌘O / Importar · exportar config / Backup · restore / Fechar aba ⌘W
Editrole do sistema (undo / redo / cut / copy / paste / select all) + Find ⌘F / Replace ⌘H / Format SQL ⌘⇧F
ViewPaleta ⌘K / Object search ⌘⇧O / Chat IA ⌘⇧L / Favoritos / Log / Zoom / Fullscreen / DevTools
ToolsServer activity / Backup / Data transfer / Schema diff / Data diff / Snapshots / Dashboard / Cross-table search / Data contracts / AI Toolbox / AI Assistant
WindowNova janela ⌘⇧N / Minimizar / Reload / (mac) trazer todas à frente
HelpSobre / Atalhos / GitHub / Reportar problema / Verificar atualizações

Implementação

Itens custom não executam lógica no main process (sem acesso ao estado Vue); enviam webContents.send('menu:command', '<key>'). Renderer assina via window.api.menu.onCommand(key => ...) no Workspace.vue e roteia para onPaletteSelect correspondente.


11. Visão geral de Settings

Local: packages/ui/src/components/SettingsDialog.vue.

5 categorias à esquerda; formulário à direita.

CategoriaPrincipais itens
GeralIdioma (zh / en) / Tema (escuro / claro) / Zoom (70-200%) / Commit mode default / NavTree por uso / Mascaramento on/off + regras
EditorFonte / indent / wrap / autocomplete / case (upper / lower / preserve)
GradePage size (50 / 100 / 200 / 500 / 1000) / texto NULL
Marca d'água prodTexto / opacidade (0.04-0.5) / ângulo (-90° a 90°) / fonte / cor; preview ao vivo
AIProvider (Anthropic / OpenAI / DeepSeek / Codex / Grok) / API Key / Model / Base URL / Memória A / B / C

Tema: Settings → Geral → Tema afeta todos os painéis. Escuro default (appearance: 'dark').

"Memória AI" três camadas

CamadaCampoSignificado
AaiCustomInstructionsPerfil em texto livre, injetado no system prompt toda hora
BaiFacts[] + aiAutoExtractFactsFatos estruturados, manuais / automáticos
CaiVectorMemory + embedding + aiVectorTopKMemória vetorial cross-session

Rodapé Restaurar default reseta tudo com confirmação.


12. Multi-janelas ⌘⇧N

Local: apps/desktop/src/main/index.ts spawnExtraWindow() + IPC window:newSession.

⌘⇧N / Ctrl+Shift+N → nova BrowserWindow (1100 × 750), mesma renderer URL, sessão totalmente independente.

Uso típico

CenárioComo
Local vs remotoPrincipal = dev local; nova = prod replica; lado a lado
Multi-tenantsJanela A para tenant A, B para tenant B
Query lenta + escritaPrincipal roda SQL longo; nova escreve a próxima

Cada janela: abas / conexão / banco / schema / cursor independentes. Histórico / favoritos / snippets são compartilhados (localStorage + SQLite único).

Sem "sincronização" (execuções de uma janela não aparecem na outra); sem gerenciador, use Mission Control / Exposé.


13. Atalhos completos

Defaults; tudo customizável em Settings → Atalhos (new-window é menu, não está em COMMANDS).

AçãomacOSWindows / LinuxID
Paleta⌘KCtrl+Kpalette
Busca de objetos⌘⇧OCtrl+Shift+Oobject-search
Executar SQL⌘+EnterCtrl+Enterrun-sql
Chat IA⌘⇧LCtrl+Shift+Lai-chat
Nova conexão / query / fechar aba⌘N / ⌘T / ⌘WCtrl+N / T / Wnew-conn / new-query / close-tab
Find / Replace / Format⌘F / ⌘H / ⌘⇧FCtrl+F / H / Shift+Ffind / replace / format-sql
Save snippet / Settings⌘S / ⌘,Ctrl+S / Ctrl+,save-snippet / settings
Nova janela⌘⇧NCtrl+Shift+N(menu)

Apache License 2.0 · Wuhan Skyler Network Technology Co., Ltd.