Private
Public Access
1
0

新增:Markdown编辑器/数据库优化/安全修复

- Markdown 编辑器:实时预览、PDF 导出、独立查看器
- 数据库优化:动态连接池、查询缓存、Redis Pipeline
- 窗口置顶功能
- 文件系统增强:右键菜单、编辑器集成、收藏夹重构
- 安全修复:XSS 防护、路径穿越、HTML 注入
- 代码质量:正则预编译、缓存锁优化、死代码清理
This commit is contained in:
2026-03-31 09:18:06 +08:00
parent 5f94ccf13b
commit e5dbe89a6f
59 changed files with 5289 additions and 1316 deletions

View File

@@ -20,6 +20,13 @@
</template>
</a-button>
</a-tooltip>
<a-tooltip :content="isPinned ? '取消置顶' : '窗口置顶'">
<a-button type="text" :class="{ 'pin-active': isPinned }" @click="handleTogglePin">
<template #icon>
<IconPushpin :class="{ pinned: isPinned }"/>
</template>
</a-button>
</a-tooltip>
<ThemeToggle/>
<!-- 窗口控制按钮 -->
@@ -71,9 +78,10 @@
</a-layout>
</template>
<script setup>
<script setup lang="ts">
import {computed, onMounted, onUnmounted, ref, watch} from 'vue'
import {IconSettings} from '@arco-design/web-vue/es/icon'
import {IconSettings, IconPushpin} from '@arco-design/web-vue/es/icon'
import MarkdownEditor from './views/markdown-editor/index.vue'
import DbCli from './views/db-cli/index.vue'
import ThemeToggle from './components/ThemeToggle.vue'
import FileSystem from './components/FileSystem/index.vue'
@@ -81,7 +89,6 @@ import SettingsPanel from './components/SettingsPanel.vue'
import UpdateNotification from './components/UpdateNotification.vue'
import {useUpdateStore} from './stores/update'
import {useConfigStore} from './stores/config'
import {preloadCommonLanguages} from './utils/codeMirrorLoader'
// 存储键
const ACTIVE_TAB_STORAGE_KEY = 'app-active-tab'
@@ -91,6 +98,7 @@ const savedTab = localStorage.getItem(ACTIVE_TAB_STORAGE_KEY)
const activeTab = ref((savedTab === 'user' ? 'file-system' : savedTab) || 'file-system')
const showSettings = ref(false)
const isMaximized = ref(false)
const isPinned = ref(false)
// 使用 stores
const updateStore = useUpdateStore()
@@ -129,21 +137,27 @@ const loadConfig = async () => {
const getComponent = (key) => {
const components = {
'file-system': FileSystem,
'db-cli': DbCli
'db-cli': DbCli,
'markdown-editor': MarkdownEditor
}
return components[key] || null
}
// 组件挂载时加载配置
// 禁止 Ctrl+滚轮缩放
const preventZoom = (e: WheelEvent) => {
if (e.ctrlKey) e.preventDefault()
}
onMounted(() => {
loadConfig()
// 预加载常用编辑器语言包
preloadCommonLanguages()
// 设置更新事件监听
updateStore.setupEventListeners()
// 禁止 Ctrl+滚轮缩放
document.addEventListener('wheel', preventZoom, { passive: false })
// 延迟检查更新(启动后 3 秒,静默模式)
setTimeout(() => {
updateStore.checkForUpdates(true)
@@ -152,6 +166,7 @@ onMounted(() => {
// 组件卸载时清理事件监听
onUnmounted(() => {
document.removeEventListener('wheel', preventZoom)
updateStore.removeEventListeners()
})
@@ -166,6 +181,16 @@ const handleMinimize = async () => {
}
}
const handleTogglePin = async () => {
try {
if (window.go?.main?.App?.WindowToggleAlwaysOnTop) {
isPinned.value = await window.go.main.App.WindowToggleAlwaysOnTop()
}
} catch (error) {
console.error('切换置顶失败:', error)
}
}
const handleMaximize = async () => {
try {
if (window.go?.main?.App?.WindowMaximize) {
@@ -282,6 +307,25 @@ watch(activeTab, (newTab) => {
color: #ffffff;
}
.pin-active {
color: rgb(var(--primary-6)) !important;
}
.pin-active :deep(svg) {
transform: none !important;
opacity: 1 !important;
}
.header-actions :deep(.arco-icon-pushpin) {
transform: rotate(45deg);
opacity: 0.6;
}
.header-actions :deep(.arco-icon-pushpin.pinned) {
transform: none;
opacity: 1;
}
.window-control-btn svg {
display: block;
pointer-events: none;