feat: 添加 Gitee 按钮、关于弹框,版本号改为 v0.1.0
- 工具栏右侧新增 Gitee 图标按钮,点击跳转项目主页 - 工具栏右侧新增关于按钮,点击打开关于弹框 - 关于弹框展示:应用图标、版本号、功能特性、技术栈、版权信息 - 点击弹框外部或关闭按钮可关闭弹框 - 版本号从 v2.0.0 改为 v0.1.0
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user