Commit 8362fbb7 by pangchong

refactor(editor): 移除圆角设置并新增树菜单尺寸配置选项

- 取消了 borderRadius 相关的状态及计算,实现圆角固定为 0
- 删除了设置抽屉中的圆角和页面切换动画选项
- 移除布局选项卡,替换为编辑区设置面板
- 新增树菜单收缩阈值、默认展开宽度和最大宽度占比的配置项
- 编辑区拖动分割条支持获取并应用树菜单尺寸相关配置
- 优化状态管理,移除冗余字段,添加树菜单相关字段
- 简化动画相关样式,移除无用动画类定义
- 确保默认设置和导入导出逻辑同步更新树菜单新配置
parent c9002bb4
......@@ -37,8 +37,6 @@ import { lightThemeConfig, darkThemeConfig } from '@/configs/tailwind.ui.config'
const appStore = useAppStore()
// 根据 borderRadius 值生成 Naive UI 的 borderRadius 字符串
const getBorderRadius = () => `${appStore.borderRadius * 16}px`
const getFontSize = () => `${appStore.fontSize}px`
// 计算 Naive UI 的主题覆写(响应式 computed)
......@@ -49,8 +47,8 @@ const lightThemeOverrides = computed<GlobalThemeOverrides>(() => ({
primaryColorHover: appStore.primaryColor + 'cc',
primaryColorPressed: appStore.primaryColor + '99',
primaryColorSuppl: appStore.primaryColor,
borderRadius: getBorderRadius(),
borderRadiusSmall: getBorderRadius(),
borderRadius: '0px',
borderRadiusSmall: '0px',
fontSize: getFontSize(),
fontSizeMedium: getFontSize(),
fontSizeLarge: `${appStore.fontSize + 2}px`,
......@@ -70,8 +68,8 @@ const darkThemeOverrides = computed<GlobalThemeOverrides>(() => ({
primaryColorHover: appStore.primaryColor + 'cc',
primaryColorPressed: appStore.primaryColor + '99',
primaryColorSuppl: appStore.primaryColor,
borderRadius: getBorderRadius(),
borderRadiusSmall: getBorderRadius(),
borderRadius: '0px',
borderRadiusSmall: '0px',
fontSize: getFontSize(),
fontSizeMedium: getFontSize(),
fontSizeLarge: `${appStore.fontSize + 2}px`,
......
......@@ -2,11 +2,9 @@
<div class="h-screen flex flex-col overflow-hidden" :style="{ backgroundColor: themeVars.bodyColor }">
<!-- 主页面视图内容区 -->
<router-view v-slot="{ Component, route }">
<transition :name="appStore.transitionName || 'none'" mode="out-in">
<keep-alive>
<component :is="Component" :key="route.fullPath" class="flex-1 flex flex-col min-h-0" />
</keep-alive>
</transition>
<keep-alive>
<component :is="Component" :key="route.fullPath" class="flex-1 flex flex-col min-h-0" />
</keep-alive>
</router-view>
<!-- 全局弹窗组件,供 window 全局挂载调用 -->
......@@ -42,47 +40,4 @@ onMounted(() => {
})
</script>
<style scoped>
/* 无动画 */
.none-enter-active,
.none-leave-active {
transition: none !important;
}
/* 淡入淡出 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
/* 滑动渐变 (原默认动画) */
.fade-slide-enter-active,
.fade-slide-leave-active {
transition: all 0.3s ease;
}
.fade-slide-enter-from {
opacity: 0;
transform: translateX(-20px);
}
.fade-slide-leave-to {
opacity: 0;
transform: translateX(20px);
}
/* 缩放渐变 */
.zoom-enter-active,
.zoom-leave-active {
transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.zoom-enter-from,
.zoom-leave-to {
opacity: 0;
transform: scale(0.96);
}
</style>
<style scoped></style>
......@@ -120,26 +120,6 @@
<n-divider class="my-4" />
<!-- 圆角 -->
<div class="mb-5">
<div class="text-sm font-semibold mb-3" :style="{ color: themeVars.textColor2 }">圆角</div>
<div class="flex gap-2">
<div
v-for="r in borderRadiusOptions"
:key="r"
class="flex-1 text-center py-1.5 rounded-lg cursor-pointer border-2 text-sm font-medium transition-all"
:style="{
borderColor: appStore.borderRadius === r ? themeVars.primaryColor : themeVars.borderColor,
color: appStore.borderRadius === r ? themeVars.primaryColor : themeVars.textColor3,
backgroundColor: appStore.borderRadius === r ? themeVars.primaryColor + '10' : 'transparent'
}"
@click="setBorderRadius(r)"
>
{{ r }}
</div>
</div>
</div>
<!-- 字体大小 -->
<div class="mb-5">
<div class="text-sm font-semibold mb-3" :style="{ color: themeVars.textColor2 }">字体大小</div>
......@@ -167,14 +147,6 @@
<n-divider class="my-4" />
<!-- 页面切换动画 -->
<div class="mb-5">
<div class="text-sm font-semibold mb-3" :style="{ color: themeVars.textColor2 }">页面切换动画</div>
<CommonSelect v-model:value="appStore.transitionName" :options="transitionOptions" placeholder="请选择切换动画" />
</div>
<n-divider class="my-4" />
<!-- 其它 -->
<div>
<div class="text-sm font-semibold mb-3" :style="{ color: themeVars.textColor2 }">其它</div>
......@@ -189,58 +161,9 @@
</div>
</n-tab-pane>
<!-- 布局 tab -->
<n-tab-pane name="layout" tab="布局">
<!-- 编辑区设置 tab -->
<n-tab-pane name="editor-settings" tab="编辑区">
<div class="space-y-1">
<div class="text-sm font-semibold mb-3" :style="{ color: themeVars.textColor2 }">界面元素</div>
<!-- 标签栏 -->
<div class="flex items-center justify-between py-3 border-b" :style="{ borderColor: themeVars.dividerColor }">
<div>
<div class="text-sm" :style="{ color: themeVars.textColor1 }">显示标签栏</div>
<div class="text-xs mt-0.5" :style="{ color: themeVars.textColor3 }">顶部多标签页导航</div>
</div>
</div>
<!-- 面包屑 -->
<div class="flex items-center justify-between py-3 border-b" :style="{ borderColor: themeVars.dividerColor }">
<div>
<div class="text-sm" :style="{ color: themeVars.textColor1 }">显示面包屑</div>
<div class="text-xs mt-0.5" :style="{ color: themeVars.textColor3 }">顶栏左侧路径导航</div>
</div>
<n-switch v-model:value="appStore.showBreadcrumb" />
</div>
<!-- 固定顶栏 -->
<div class="flex items-center justify-between py-3 border-b" :style="{ borderColor: themeVars.dividerColor }">
<div>
<div class="text-sm" :style="{ color: themeVars.textColor1 }">固定顶栏</div>
<div class="text-xs mt-0.5" :style="{ color: themeVars.textColor3 }">滚动时顶栏保持可见</div>
</div>
<n-switch v-model:value="appStore.fixedHeader" />
</div>
<!-- 紧凑模式 -->
<div class="flex items-center justify-between py-3 border-b" :style="{ borderColor: themeVars.dividerColor }">
<div>
<div class="text-sm" :style="{ color: themeVars.textColor1 }">紧凑模式</div>
<div class="text-xs mt-0.5" :style="{ color: themeVars.textColor3 }">减少内容区内边距</div>
</div>
<n-switch v-model:value="appStore.contentCompact" />
</div>
<!-- 侧边栏 -->
<div class="flex items-center justify-between py-3" :style="{ borderColor: themeVars.dividerColor }">
<div>
<div class="text-sm" :style="{ color: themeVars.textColor1 }">折叠侧边栏</div>
<div class="text-xs mt-0.5" :style="{ color: themeVars.textColor3 }">收起左侧导航菜单</div>
</div>
<n-switch v-model:value="appStore.collapsed" />
</div>
<n-divider class="my-4" />
<div class="text-sm font-semibold mb-3" :style="{ color: themeVars.textColor2 }">编辑器设置</div>
<!-- 自动展开新增节点 -->
<div class="flex items-center justify-between py-3 border-b" :style="{ borderColor: themeVars.dividerColor }">
<div>
......@@ -251,7 +174,7 @@
</div>
<!-- 表格新增列默认宽度 -->
<div class="py-3" :style="{ borderColor: themeVars.dividerColor }">
<div class="py-3 border-b" :style="{ borderColor: themeVars.dividerColor }">
<div class="flex items-center justify-between mb-1.5">
<span class="text-sm" :style="{ color: themeVars.textColor1 }">表格新增列默认宽度比</span>
<div class="w-32">
......@@ -268,6 +191,69 @@
</div>
<div class="text-xs" :style="{ color: themeVars.textColor3 }">设定新增列占常规平分列宽的比例或折算系数</div>
</div>
<!-- 树菜单收缩阈值 -->
<div class="py-3 border-b" :style="{ borderColor: themeVars.dividerColor }">
<div class="flex items-center justify-between mb-1.5">
<div>
<div class="text-sm" :style="{ color: themeVars.textColor1 }">树菜单收缩阈值</div>
<div class="text-xs mt-0.5" :style="{ color: themeVars.textColor3 }">拖动到小于此像素值时将自动收缩</div>
</div>
<div class="w-32">
<CommonInputNumber
v-model:value="appStore.treeCollapseThreshold"
:min="10"
:max="500"
:step="5"
:strict="true"
size="small"
placeholder="默认 20"
/>
</div>
</div>
</div>
<!-- 树菜单默认展开宽度 -->
<div class="py-3 border-b" :style="{ borderColor: themeVars.dividerColor }">
<div class="flex items-center justify-between mb-1.5">
<div>
<div class="text-sm" :style="{ color: themeVars.textColor1 }">树菜单默认展开宽度</div>
<div class="text-xs mt-0.5" :style="{ color: themeVars.textColor3 }">点击展开时的分栏宽度(px)</div>
</div>
<div class="w-32">
<CommonInputNumber
v-model:value="appStore.treeDefaultWidth"
:min="100"
:max="1200"
:step="10"
:strict="true"
size="small"
placeholder="默认 560"
/>
</div>
</div>
</div>
<!-- 树菜单最大宽度占比 -->
<div class="py-3" :style="{ borderColor: themeVars.dividerColor }">
<div class="flex items-center justify-between mb-1.5">
<div>
<div class="text-sm" :style="{ color: themeVars.textColor1 }">树菜单最大宽度占比</div>
<div class="text-xs mt-0.5" :style="{ color: themeVars.textColor3 }">拖动树分栏时占窗口最大宽度的比例</div>
</div>
<div class="w-32">
<CommonInputNumber
v-model:value="appStore.treeMaxRatio"
:min="0.1"
:max="0.9"
:step="0.05"
:strict="true"
size="small"
placeholder="默认 0.6"
/>
</div>
</div>
</div>
</div>
</n-tab-pane>
......@@ -311,7 +297,6 @@
导入
</CommonButton>
</n-space>
<CommonButton text type="error" size="small" @click="clearAndLogout">清空并退出</CommonButton>
</div>
</template>
</n-drawer-content>
......@@ -335,7 +320,6 @@ import { useAppStore } from '@/store/app/index'
const themeVars = useThemeVars()
const appStore = useAppStore()
const router = useRouter()
const customColor = ref(appStore.primaryColor)
......@@ -366,20 +350,12 @@ const colorPresets = [
{ label: '中灰色', color: '#9CA3AF' }
]
const borderRadiusOptions = [0, 0.25, 0.5, 0.75, 1]
const transitionOptions = [
{ label: '无动画', value: 'none' },
{ label: '淡入淡出', value: 'fade' },
{ label: '滑动渐变', value: 'fade-slide' },
{ label: '缩放渐变', value: 'zoom' }
]
const shortcuts = [
{ label: '全局搜索', keys: ['Ctrl', 'K'] },
{ label: '切换主题', keys: ['Ctrl', 'Shift', 'D'] },
{ label: '返回首页', keys: ['Alt', 'H'] },
{ label: '关闭当前标签', keys: ['Alt', 'W'] }
{ label: '撤销', keys: ['Ctrl', 'Z'] },
{ label: '重做', keys: ['Ctrl', 'Y'] },
{ label: '查找', keys: ['Ctrl', 'F'] },
{ label: '取消 / ESC', keys: ['Escape'] }
]
const setThemeMode = (mode: string) => {
......@@ -397,11 +373,6 @@ const setColor = (color: string) => {
applyAndSave()
}
const setBorderRadius = (r: number) => {
appStore.borderRadius = r
applyAndSave()
}
const applyAndSave = () => {
appStore.applyTheme()
}
......@@ -418,18 +389,15 @@ const increaseFontSize = () => {
const resetPrefs = () => {
appStore.primaryColor = '#165DFF'
appStore.borderRadius = 0
appStore.fontSize = 14
appStore.colorWeak = false
appStore.grayMode = false
appStore.isDark = false
appStore.showBreadcrumb = true
appStore.contentCompact = true
appStore.fixedHeader = false
appStore.collapsed = false
appStore.transitionName = 'none'
appStore.autoExpandOnInsert = true
appStore.defaultNewColWidth = 0.2
appStore.treeCollapseThreshold = 20
appStore.treeDefaultWidth = 560
appStore.treeMaxRatio = 0.6
customColor.value = '#165DFF'
applyAndSave()
window.$message.success('已重置为默认设置')
......@@ -439,14 +407,15 @@ const copyPrefs = async () => {
const prefs = JSON.stringify(
{
primaryColor: appStore.primaryColor,
borderRadius: appStore.borderRadius,
fontSize: appStore.fontSize,
isDark: appStore.isDark,
colorWeak: appStore.colorWeak,
grayMode: appStore.grayMode,
transitionName: appStore.transitionName,
autoExpandOnInsert: appStore.autoExpandOnInsert,
defaultNewColWidth: appStore.defaultNewColWidth
defaultNewColWidth: appStore.defaultNewColWidth,
treeCollapseThreshold: appStore.treeCollapseThreshold,
treeDefaultWidth: appStore.treeDefaultWidth,
treeMaxRatio: appStore.treeMaxRatio
},
null,
2
......@@ -470,14 +439,15 @@ const importPrefs = async () => {
// 验证关键字段
if (conf.primaryColor) appStore.primaryColor = conf.primaryColor
if (typeof conf.borderRadius === 'number') appStore.borderRadius = conf.borderRadius
if (typeof conf.fontSize === 'number') appStore.fontSize = conf.fontSize
if (typeof conf.isDark === 'boolean') appStore.isDark = conf.isDark
if (typeof conf.colorWeak === 'boolean') appStore.colorWeak = conf.colorWeak
if (typeof conf.grayMode === 'boolean') appStore.grayMode = conf.grayMode
if (conf.transitionName) appStore.transitionName = conf.transitionName
if (typeof conf.autoExpandOnInsert === 'boolean') appStore.autoExpandOnInsert = conf.autoExpandOnInsert
if (typeof conf.defaultNewColWidth === 'number') appStore.defaultNewColWidth = conf.defaultNewColWidth
if (typeof conf.treeCollapseThreshold === 'number') appStore.treeCollapseThreshold = conf.treeCollapseThreshold
if (typeof conf.treeDefaultWidth === 'number') appStore.treeDefaultWidth = conf.treeDefaultWidth
if (typeof conf.treeMaxRatio === 'number') appStore.treeMaxRatio = conf.treeMaxRatio
applyAndSave()
window.$message.success('偏好设置已成功导入并应用')
......@@ -486,20 +456,6 @@ const importPrefs = async () => {
}
}
const clearAndLogout = async () => {
try {
await window.$dialog.warning({
title: '确认清空并退出',
content: '确定要清空所有本地缓存并退出登录吗?此操作不可逆。'
})
localStorage.clear()
router.push('/login')
window.$message.success('已清空并退出')
} catch (error) {
// User cancelled
}
}
onMounted(() => {
applyAndSave()
})
......
......@@ -2,35 +2,28 @@ import type { AppState } from './types'
export const useAppStore = defineStore('app', {
state: (): AppState => ({
collapsed: false,
isDark: false,
primaryColor: '#165DFF',
borderRadius: 0,
fontSize: 14,
colorWeak: false,
grayMode: false,
showBreadcrumb: true,
contentCompact: true,
fixedHeader: false,
rememberMe: false,
savedUsername: '',
savedPassword: '',
loading: false,
loadingText: '加载中...',
transitionName: 'none',
settingsPinned: false,
settingsOpen: false,
autoExpandOnInsert: true,
defaultNewColWidth: 0.2
defaultNewColWidth: 0.2,
treeCollapseThreshold: 20,
treeDefaultWidth: 560,
treeMaxRatio: 0.6
}),
actions: {
toggleSidebar() {
this.collapsed = !this.collapsed
},
applyTheme() {
const root = document.documentElement
root.style.setProperty('--primary-color', this.primaryColor)
root.style.setProperty('--border-radius-base', `${this.borderRadius}rem`)
root.style.setProperty('--font-size-base', `${this.fontSize}px`)
document.body.style.fontSize = `${this.fontSize}px`
document.body.classList.toggle('color-weak', this.colorWeak)
......
export interface AppState {
collapsed: boolean
isDark: boolean
primaryColor: string
borderRadius: number
fontSize: number
colorWeak: boolean
grayMode: boolean
// 布局
showBreadcrumb: boolean
contentCompact: boolean
fixedHeader: boolean
rememberMe: boolean
savedUsername: string
savedPassword: string
// 全局加载状态
loading: boolean
loadingText?: string
transitionName: string
settingsPinned: boolean
settingsOpen: boolean
autoExpandOnInsert: boolean // 新增/粘贴节点及表格行列时自动展开
defaultNewColWidth: number // 表格新增列的默认宽度比例 (当前默认 0.2)
treeCollapseThreshold: number // 树分栏收缩阈值
treeDefaultWidth: number // 树分栏默认展开宽度
treeMaxRatio: number // 树分栏最大宽度比例
}
......@@ -7,9 +7,9 @@ export function useSplitter(
(e: 'update:collapsed', val: boolean): void
}
) {
const collapseThreshold = props.collapseThreshold ?? 150
const defaultWidth = props.defaultWidth ?? 560
const maxRatio = props.maxRatio ?? 0.6
const collapseThreshold = computed(() => props.collapseThreshold ?? 20)
const defaultWidth = computed(() => props.defaultWidth ?? 560)
const maxRatio = computed(() => props.maxRatio ?? 0.6)
const dividerRef = ref<HTMLElement | null>(null)
const isDragging = ref(false)
......@@ -42,11 +42,11 @@ export function useSplitter(
if (Math.abs(delta) > 3) hasDragged = true
const raw = startWidth + delta
const containerWidth = containerEl.clientWidth
const maxWidth = containerWidth * maxRatio
const maxWidth = containerWidth * maxRatio.value
if (raw < collapseThreshold) {
if (raw < collapseThreshold.value) {
emit('update:width', Math.max(0, raw))
emit('update:collapsed', raw < collapseThreshold / 2)
emit('update:collapsed', raw < collapseThreshold.value / 2)
} else {
emit('update:collapsed', false)
emit('update:width', Math.min(maxWidth, raw))
......@@ -60,7 +60,7 @@ export function useSplitter(
window.removeEventListener('mousemove', onDrag)
window.removeEventListener('mouseup', stopDrag)
if (!props.collapsed && props.width < collapseThreshold) {
if (!props.collapsed && props.width < collapseThreshold.value) {
emit('update:collapsed', true)
}
}
......@@ -69,7 +69,7 @@ export function useSplitter(
if (hasDragged) return
if (props.collapsed) {
emit('update:collapsed', false)
emit('update:width', defaultWidth)
emit('update:width', defaultWidth.value)
}
}
......
......@@ -36,7 +36,7 @@ const props = withDefaults(
maxRatio?: number
}>(),
{
collapseThreshold: 150,
collapseThreshold: 20,
defaultWidth: 560,
maxRatio: 0.6
}
......
......@@ -23,7 +23,13 @@
</div>
<!-- 拖动分割条组件 -->
<Splitter v-model:width="leftWidthPx" v-model:collapsed="isCollapsed" />
<Splitter
v-model:width="leftWidthPx"
v-model:collapsed="isCollapsed"
:collapse-threshold="appStore.treeCollapseThreshold"
:default-width="appStore.treeDefaultWidth"
:max-ratio="appStore.treeMaxRatio"
/>
<!-- 右侧:编辑区 -->
<div class="flex-1 flex flex-col overflow-hidden" :style="{ background: themeVars.colorBg1 }">
......@@ -40,6 +46,7 @@
<script setup lang="ts">
import { useEditorStore } from '@/store/editor'
import { useAppStore } from '@/store/app'
import { useEditor } from './functionals'
import EditorToolbar from './components/EditorToolbar/index.vue'
import NodeTree from './components/NodeTree/index.vue'
......@@ -49,13 +56,14 @@ import DocNodeRenderer from './components/DocNodeRenderer/index.vue'
const themeVars = useThemeVars()
const editorStore = useEditorStore()
const appStore = useAppStore()
const expandedKeys = computed({
get: () => editorStore.expandedKeys,
set: (val) => editorStore.setExpandedKeys(val)
})
// 界面拖动分割状态
const leftWidthPx = ref(560)
const leftWidthPx = ref(appStore.treeDefaultWidth)
const isCollapsed = ref(false)
// 实例化业务逻辑 Hook
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment