Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion frontend/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="app-container">
<Toolbar
<Toolbar
:is-connected="hasActiveConnection"
:is-dark="theme === 'dark'"
@connect="handleConnect"
Expand All @@ -11,6 +11,7 @@
@toggle-sidebar="sidebarCollapsed = !sidebarCollapsed"
@toggle-history="historyVisible = !historyVisible"
@toggle-settings="settingsVisible = true"
@toggle-about="aboutVisible = true"
/>

<div class="main-content">
Expand Down Expand Up @@ -65,6 +66,12 @@
@save="handleSaveSettings"
@reset="handleResetSettings"
/>

<!-- 添加关于弹窗 -->
<About
:visible="aboutVisible"
@close="aboutVisible = false"
/>
</div>
</template>

Expand All @@ -77,6 +84,7 @@ import QueryEditor from './components/QueryEditor.vue'
import ResultsTable from './components/ResultsTable.vue'
import QueryHistory from './components/QueryHistory.vue'
import Settings from './components/Settings.vue'
import About from './components/About.vue'
import { useTheme } from './composables/useTheme'
import { useSettings } from './composables/useSettings'
import type { SavedConnection, QueryHistoryItem, Database, AppSettings } from './types'
Expand All @@ -92,6 +100,7 @@ const toggleTheme = themeComposable.toggleTheme

const appSettings = settingsComposable.settings
const settingsVisible = ref(false)
const aboutVisible = ref(false)

const query = ref('SELECT * FROM measurement_name LIMIT 100')
const resultColumns = ref<string[]>([])
Expand Down
224 changes: 224 additions & 0 deletions frontend/src/components/About.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
<template>
<div v-if="visible" class="about-overlay" @click.self="$emit('close')">
<div class="about-modal">
<div class="about-header">
<h2>{{ $t('about.title') }}</h2>
<button @click="$emit('close')" class="close-btn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"/>
<line x1="6" y1="6" x2="18" y2="18"/>
</svg>
</button>
</div>

<div class="about-content">
<div class="about-section">
<p class="about-description">{{ $t('about.description') }}</p>
</div>

<div class="about-section">
<h3>{{ $t('about.links') }}</h3>
<div class="links-container">
<a
href="https://github.com/openGemini/openGemini-studio"
target="_blank"
rel="noopener noreferrer"
class="link-item"
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/>
</svg>
<span>{{ $t('about.repository') }}</span>
<svg class="external-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" y1="14" x2="21" y2="3"/>
</svg>
</a>

<a
href="https://github.com/openGemini/openGemini"
target="_blank"
rel="noopener noreferrer"
class="link-item"
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/>
</svg>
<span>{{ $t('about.mainRepository') }}</span>
<svg class="external-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" y1="14" x2="21" y2="3"/>
</svg>
</a>
</div>
</div>
</div>

<div class="about-footer">
<button @click="$emit('close')" class="btn btn-primary">{{ $t('common.close') }}</button>
</div>
</div>
</div>
</template>

<script setup lang="ts">
defineProps<{
visible: boolean
}>()

defineEmits<{
close: []
}>()
</script>

<style scoped>
.about-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}

.about-modal {
background: var(--bg-secondary);
border-radius: 8px;
width: 90%;
max-width: 600px;
max-height: 80vh;
display: flex;
flex-direction: column;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.about-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
border-bottom: 1px solid var(--border-color);
}

.about-header h2 {
margin: 0;
font-size: 20px;
font-weight: 600;
color: var(--text-primary);
}

.close-btn {
background: transparent;
border: none;
color: var(--text-secondary);
cursor: pointer;
padding: 4px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: all 0.2s;
}

.close-btn:hover {
background: var(--bg-hover);
color: var(--text-primary);
}

.about-content {
flex: 1;
overflow-y: auto;
padding: 20px;
}

.about-section {
margin-bottom: 24px;
}

.about-section:last-child {
margin-bottom: 0;
}

.about-section h3 {
margin: 0 0 12px 0;
font-size: 16px;
font-weight: 600;
color: var(--text-primary);
}

.about-description {
margin: 0;
font-size: 14px;
line-height: 1.6;
color: var(--text-secondary);
}

.links-container {
display: flex;
flex-direction: column;
gap: 12px;
}

.link-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: var(--bg-tertiary);
border: 1px solid var(--border-color);
border-radius: 6px;
color: var(--text-primary);
text-decoration: none;
transition: all 0.2s;
}

.link-item:hover {
background: var(--bg-hover);
border-color: #3b82f6;
}

.link-item span {
flex: 1;
font-size: 14px;
}

.link-item svg {
flex-shrink: 0;
}

.external-icon {
color: var(--text-secondary);
}

.about-footer {
display: flex;
justify-content: flex-end;
padding: 20px;
border-top: 1px solid var(--border-color);
}

.btn {
padding: 10px 20px;
border: none;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}

.btn-primary {
background: #3b82f6;
color: white;
}

.btn-primary:hover {
background: #2563eb;
}
</style>
12 changes: 10 additions & 2 deletions frontend/src/components/Toolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@
</svg>
</button>
<button @click="$emit('toggleSettings')" class="btn btn-icon" :title="$t('toolbar.settings')">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3"/>
<path d="M12 1v6m0 6v6M5.64 5.64l4.24 4.24m4.24 4.24l4.24 4.24M1 12h6m6 0h6M5.64 18.36l4.24-4.24m4.24-4.24l4.24-4.24"/>
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/>
</svg>
</button>
<button @click="$emit('toggleAbout')" class="btn btn-icon" :title="$t('toolbar.about')">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"/>
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/>
<line x1="12" y1="17" x2="12.01" y2="17"/>
</svg>
</button>

Expand Down Expand Up @@ -73,6 +80,7 @@ defineEmits<{
toggleSidebar: []
toggleHistory: []
toggleSettings: []
toggleAbout: []
}>()
</script>

Expand Down
8 changes: 8 additions & 0 deletions frontend/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default {
export: 'Export CSV',
history: 'Query History',
settings: 'Settings',
about: 'About',
toggleTheme: 'Toggle Theme',
toggleSidebar: 'Toggle Sidebar',
},
Expand Down Expand Up @@ -141,4 +142,11 @@ export default {
loadSettingsFailed: 'Failed to load settings',
saveSettingsFailed: 'Failed to save settings',
},
about: {
title: 'About openGemini Studio',
description: 'A modern, cross-platform desktop client for openGemini time-series database. Built with Wails, Vue 3, and TypeScript to provide a native desktop experience for database management, query execution, and data visualization.',
links: 'Links',
repository: 'openGemini Studio Repository',
mainRepository: 'openGemini Repository',
},
}
8 changes: 8 additions & 0 deletions frontend/src/locales/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default {
export: '导出CSV',
history: '查询历史',
settings: '设置',
about: '关于',
toggleTheme: '切换主题',
toggleSidebar: '切换侧边栏',
},
Expand Down Expand Up @@ -141,4 +142,11 @@ export default {
loadSettingsFailed: '加载设置失败',
saveSettingsFailed: '保存设置失败',
},
about: {
title: '关于 openGemini Studio',
description: '一个现代化的跨平台 openGemini 时序数据库桌面客户端。使用 Wails、Vue 3 和 TypeScript 构建,提供原生桌面体验,支持数据库管理、查询执行和数据可视化。',
links: '链接',
repository: 'openGemini Studio 仓库',
mainRepository: 'openGemini 仓库',
},
}