feat: 添加 Gitee 按钮、关于弹框,版本号改为 v0.1.0

- 工具栏右侧新增 Gitee 图标按钮,点击跳转项目主页
- 工具栏右侧新增关于按钮,点击打开关于弹框
- 关于弹框展示:应用图标、版本号、功能特性、技术栈、版权信息
- 点击弹框外部或关闭按钮可关闭弹框
- 版本号从 v2.0.0 改为 v0.1.0
This commit is contained in:
thzxx
2026-05-28 15:38:29 +08:00
parent 3294dd585c
commit 03a71bdf94
5 changed files with 180 additions and 3 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "marklite",
"version": "2.0.0",
"version": "0.1.0",
"description": "Lightweight Markdown Editor for Windows",
"main": "./dist/main/index.js",
"scripts": {
+36
View File
@@ -19,6 +19,9 @@ import { WelcomeScreen } from './components/WelcomeScreen/WelcomeScreen'
import { Toast } from './components/Toast/Toast'
import { ModifiedBanner } from './components/ModifiedBanner/ModifiedBanner'
import { DropOverlay } from './components/DropOverlay/DropOverlay'
import { AppIcon } from './components/Icons'
const APP_VERSION = 'v0.1.0'
export default function App() {
const tabs = useTabStore(s => s.tabs)
@@ -38,6 +41,7 @@ export default function App() {
const [showModifiedBanner, setShowModifiedBanner] = useState(false)
const [modifiedFilePath, setModifiedFilePath] = useState<string | null>(null)
const [toastMessage, setToastMessage] = useState<string | null>(null)
const [showAbout, setShowAbout] = useState(false)
const toastTimer = useRef<number>(0)
// 启动时从 IndexedDB 加载标签页和 sidebar 设置
@@ -184,6 +188,7 @@ export default function App() {
onViewModeChange={handleViewModeChange}
darkMode={darkMode}
onToggleDark={toggleDarkMode}
onShowAbout={() => setShowAbout(true)}
/>
<div id="workspace">
@@ -239,6 +244,37 @@ export default function App() {
{toastMessage && <Toast message={toastMessage} />}
<DropOverlay />
{/* 关于弹框 */}
{showAbout && (
<div className="about-overlay" onClick={() => setShowAbout(false)}>
<div className="about-dialog" onClick={e => e.stopPropagation()}>
<div className="about-header">
<AppIcon size={64} />
<h2>MarkLite</h2>
<span className="about-version">{APP_VERSION}</span>
</div>
<div className="about-body">
<p> Windows Markdown </p>
<div className="about-features">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<div className="about-footer">
<p> Electron + React + TypeScript </p>
<p className="about-copyright">© 2026 thzxx</p>
</div>
<button className="about-close-btn" onClick={() => setShowAbout(false)}></button>
</div>
</div>
)}
</div>
)
}
+19
View File
@@ -104,6 +104,25 @@ export function Sun({ size = defaultProps.size }: IconProps) {
)
}
// ===== 工具栏右侧图标 =====
export function Gitee({ size = defaultProps.size }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
<path d="M11.984 0C5.372 0 0 5.372 0 11.984c0 6.612 5.372 11.984 11.984 11.984s11.984-5.372 11.984-11.984C23.968 5.372 18.596 0 11.984 0zm6.78 18.272c-.224.448-.832.672-1.344.448l-3.584-1.792c-.448-.224-.672-.448-.672-.896v-4.704c0-.448.448-.896.896-.896h4.704c.448 0 .896.448.896.896v4.704c0 .896-.448 1.568-1.344 1.792l.448.64zm-6.112-2.688c-.896 0-1.568-.672-1.568-1.568s.672-1.568 1.568-1.568 1.568.672 1.568 1.568-.672 1.568-1.568 1.568z"/>
</svg>
)
}
export function Info({ size = defaultProps.size }: IconProps) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="10"/>
<line x1="12" y1="16" x2="12" y2="12"/>
<line x1="12" y1="8" x2="12.01" y2="8"/>
</svg>
)
}
// ===== 标签栏图标 =====
export function Close({ size = 10 }: IconProps) {
return (
+17 -2
View File
@@ -1,5 +1,5 @@
import React from 'react'
import { FolderOpen, Save, EditMode, PreviewMode, Moon, Sun } from '../Icons'
import { FolderOpen, Save, EditMode, PreviewMode, Moon, Sun, Gitee, Info } from '../Icons'
interface ToolbarProps {
onOpen: () => void
@@ -8,9 +8,18 @@ interface ToolbarProps {
onViewModeChange: (mode: 'editor' | 'preview') => void
darkMode: boolean
onToggleDark: () => void
onShowAbout: () => void
}
export function Toolbar({ onOpen, onSave, viewMode, onViewModeChange, darkMode, onToggleDark }: ToolbarProps) {
export function Toolbar({ onOpen, onSave, viewMode, onViewModeChange, darkMode, onToggleDark, onShowAbout }: ToolbarProps) {
const handleOpenGitee = () => {
if (window.electronAPI?.openExternal) {
window.electronAPI.openExternal('https://gitee.com/thzxx/MarkLite')
} else {
window.open('https://gitee.com/thzxx/MarkLite', '_blank')
}
}
return (
<div id="toolbar">
<div className="toolbar-left">
@@ -36,6 +45,12 @@ export function Toolbar({ onOpen, onSave, viewMode, onViewModeChange, darkMode,
<button className="toolbar-btn" onClick={onToggleDark} title="切换暗色主题">
{darkMode ? <Sun size={18} /> : <Moon size={18} />}
</button>
<button className="toolbar-btn" onClick={handleOpenGitee} title="Gitee 项目主页">
<Gitee size={18} />
</button>
<button className="toolbar-btn" onClick={onShowAbout} title="关于">
<Info size={18} />
</button>
</div>
</div>
)
+107
View File
@@ -1081,3 +1081,110 @@ html, body {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
/* About Dialog */
.about-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 10000;
animation: fadeIn 0.2s ease;
}
.about-dialog {
background: var(--bg);
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
padding: 32px;
width: 360px;
max-width: 90vw;
text-align: center;
animation: fadeIn 0.2s ease;
}
.about-header {
margin-bottom: 20px;
}
.about-header h2 {
margin: 12px 0 4px;
font-size: 24px;
font-weight: 600;
color: var(--text);
}
.about-version {
display: inline-block;
background: var(--primary-light);
color: var(--primary);
padding: 2px 10px;
border-radius: 12px;
font-size: 13px;
font-weight: 500;
}
.about-body {
margin-bottom: 20px;
}
.about-body > p {
color: var(--text-secondary);
font-size: 14px;
margin-bottom: 16px;
}
.about-features {
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
}
.about-features span {
background: var(--bg-secondary);
color: var(--text-secondary);
padding: 4px 12px;
border-radius: 6px;
font-size: 12px;
border: 1px solid var(--border-light);
}
.about-footer {
padding-top: 16px;
border-top: 1px solid var(--border-light);
margin-bottom: 20px;
}
.about-footer p {
color: var(--text-tertiary);
font-size: 12px;
margin: 4px 0;
}
.about-copyright {
font-weight: 500;
}
.about-close-btn {
width: 100%;
padding: 10px;
background: var(--primary);
color: white;
border: none;
border-radius: 8px;
font-size: 14px;
font-family: var(--font-ui);
font-weight: 500;
cursor: pointer;
transition: background 0.15s ease;
}
.about-close-btn:hover {
background: var(--primary-dark);
}