md2ui 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/bin/md2ui.js +6 -3
- package/package.json +1 -1
- package/src/App.vue +55 -20
- package/src/api/docs.js +3 -1
- package/src/components/Logo.vue +3 -3
- package/src/components/TableOfContents.vue +9 -4
- package/src/components/TreeNode.vue +55 -2
- package/src/config.js +8 -0
- package/src/style.css +232 -411
- package/vite.config.js +2 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# md2ui
|
|
2
2
|
|
|
3
|
+
[](https://github.com/devsneed/md2ui)
|
|
4
|
+
|
|
3
5
|
一个轻量级的文档渲染系统,将本地 Markdown 文档转换为美观的 HTML 页面。
|
|
4
6
|
|
|
5
7
|
## 核心特性
|
|
@@ -63,7 +65,7 @@ your-docs/
|
|
|
63
65
|
|
|
64
66
|
```bash
|
|
65
67
|
# 克隆项目
|
|
66
|
-
git clone https://github.com/
|
|
68
|
+
git clone https://github.com/devsneed/md2ui.git
|
|
67
69
|
cd md2ui
|
|
68
70
|
|
|
69
71
|
# 安装依赖
|
|
@@ -81,8 +83,8 @@ pnpm dev
|
|
|
81
83
|
### 本地测试 CLI
|
|
82
84
|
|
|
83
85
|
```bash
|
|
84
|
-
#
|
|
85
|
-
|
|
86
|
+
# 安装到全局
|
|
87
|
+
npm install -g .
|
|
86
88
|
|
|
87
89
|
# 在任意目录测试
|
|
88
90
|
cd /path/to/test/docs
|
package/bin/md2ui.js
CHANGED
|
@@ -10,16 +10,19 @@ const __filename = fileURLToPath(import.meta.url)
|
|
|
10
10
|
const __dirname = dirname(__filename)
|
|
11
11
|
const pkgRoot = resolve(__dirname, '..')
|
|
12
12
|
|
|
13
|
+
// 导入共享配置
|
|
14
|
+
const { config } = await import(resolve(pkgRoot, 'src/config.js'))
|
|
15
|
+
|
|
13
16
|
// 用户执行命令的目录
|
|
14
17
|
const userDir = process.cwd()
|
|
15
18
|
|
|
16
19
|
// 解析命令行参数
|
|
17
20
|
const args = process.argv.slice(2)
|
|
18
|
-
let port =
|
|
21
|
+
let port = config.defaultPort
|
|
19
22
|
|
|
20
23
|
for (let i = 0; i < args.length; i++) {
|
|
21
24
|
if (args[i] === '-p' || args[i] === '--port') {
|
|
22
|
-
port = parseInt(args[i + 1]) ||
|
|
25
|
+
port = parseInt(args[i + 1]) || config.defaultPort
|
|
23
26
|
}
|
|
24
27
|
}
|
|
25
28
|
|
|
@@ -70,7 +73,7 @@ function scanDocs(dir, basePath = '', level = 0) {
|
|
|
70
73
|
order: match ? parseInt(match[1]) : 999,
|
|
71
74
|
type: 'folder',
|
|
72
75
|
level,
|
|
73
|
-
expanded:
|
|
76
|
+
expanded: config.folderExpanded,
|
|
74
77
|
children
|
|
75
78
|
})
|
|
76
79
|
}
|
package/package.json
CHANGED
package/src/App.vue
CHANGED
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
<div class="container">
|
|
3
3
|
<aside v-if="!sidebarCollapsed" class="sidebar" :style="{ width: sidebarWidth + 'px' }">
|
|
4
4
|
<div class="logo">
|
|
5
|
-
<
|
|
5
|
+
<div class="logo-group">
|
|
6
|
+
<Logo @go-home="loadFirstDoc" />
|
|
7
|
+
<a href="https://github.com/devsneed/md2ui" target="_blank" class="github-link" title="GitHub">
|
|
8
|
+
<Github :size="14" />
|
|
9
|
+
</a>
|
|
10
|
+
</div>
|
|
11
|
+
<button class="sidebar-toggle" @click="sidebarCollapsed = true" title="收起导航">
|
|
12
|
+
<PanelLeftClose :size="16" />
|
|
13
|
+
</button>
|
|
6
14
|
</div>
|
|
7
15
|
<nav class="nav-menu">
|
|
8
16
|
<div class="nav-section">
|
|
@@ -30,20 +38,14 @@
|
|
|
30
38
|
<button v-if="sidebarCollapsed" class="expand-btn expand-btn-left" @click="sidebarCollapsed = false" title="展开导航">
|
|
31
39
|
<PanelLeftOpen :size="16" />
|
|
32
40
|
</button>
|
|
33
|
-
<button v-else class="collapse-btn collapse-btn-left" @click="sidebarCollapsed = true" title="收起导航">
|
|
34
|
-
<PanelLeftClose :size="16" />
|
|
35
|
-
</button>
|
|
36
41
|
<main class="content" @scroll="handleScroll" @click="handleContentClick">
|
|
37
42
|
<article class="markdown-content" v-html="htmlContent"></article>
|
|
38
43
|
</main>
|
|
39
44
|
<div v-if="!tocCollapsed && tocItems.length > 0" class="resizer resizer-right" @mousedown="startResize('right', $event)"></div>
|
|
40
|
-
<TableOfContents :tocItems="tocItems" :activeHeading="activeHeading" :collapsed="tocCollapsed" :width="tocWidth" @scroll-to="scrollToHeading" />
|
|
45
|
+
<TableOfContents :tocItems="tocItems" :activeHeading="activeHeading" :collapsed="tocCollapsed" :width="tocWidth" @toggle="tocCollapsed = !tocCollapsed" @scroll-to="scrollToHeading" />
|
|
41
46
|
<button v-if="tocCollapsed && tocItems.length > 0" class="expand-btn expand-btn-right" @click="tocCollapsed = false" title="展开目录">
|
|
42
47
|
<PanelRightOpen :size="16" />
|
|
43
48
|
</button>
|
|
44
|
-
<button v-else-if="tocItems.length > 0" class="collapse-btn collapse-btn-right" @click="tocCollapsed = true" title="收起目录">
|
|
45
|
-
<PanelRightClose :size="16" />
|
|
46
|
-
</button>
|
|
47
49
|
<transition name="fade">
|
|
48
50
|
<button v-if="showBackToTop" class="back-to-top" @click="scrollToTop" title="返回顶部">
|
|
49
51
|
<ArrowUp :size="20" />
|
|
@@ -56,7 +58,7 @@
|
|
|
56
58
|
|
|
57
59
|
<script setup>
|
|
58
60
|
import { ref, onMounted } from 'vue'
|
|
59
|
-
import { ChevronsDownUp, ChevronsUpDown, ArrowUp, PanelLeftOpen, PanelLeftClose, PanelRightOpen,
|
|
61
|
+
import { ChevronsDownUp, ChevronsUpDown, ArrowUp, PanelLeftOpen, PanelLeftClose, PanelRightOpen, Github } from 'lucide-vue-next'
|
|
60
62
|
import Logo from './components/Logo.vue'
|
|
61
63
|
import TreeNode from './components/TreeNode.vue'
|
|
62
64
|
import TableOfContents from './components/TableOfContents.vue'
|
|
@@ -81,16 +83,11 @@ async function loadDocsList() {
|
|
|
81
83
|
docsList.value = await getDocsList()
|
|
82
84
|
}
|
|
83
85
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const content = await response.text()
|
|
90
|
-
await renderMarkdown(content)
|
|
91
|
-
}
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.error('加载首页失败:', error)
|
|
86
|
+
// 加载第一个文档
|
|
87
|
+
function loadFirstDoc() {
|
|
88
|
+
const firstDoc = findFirstDoc(docsList.value)
|
|
89
|
+
if (firstDoc) {
|
|
90
|
+
loadDoc(firstDoc.key)
|
|
94
91
|
}
|
|
95
92
|
}
|
|
96
93
|
|
|
@@ -164,8 +161,46 @@ function handleContentClick(event) {
|
|
|
164
161
|
}
|
|
165
162
|
}
|
|
166
163
|
|
|
164
|
+
// 查找第一个文档
|
|
165
|
+
function findFirstDoc(items) {
|
|
166
|
+
for (const item of items) {
|
|
167
|
+
if (item.type === 'file') return item
|
|
168
|
+
if (item.type === 'folder' && item.children) {
|
|
169
|
+
const found = findFirstDoc(item.children)
|
|
170
|
+
if (found) return found
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return null
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 显示无文档提示
|
|
177
|
+
function showEmptyMessage() {
|
|
178
|
+
renderMarkdown(`# 当前目录没有 Markdown 文档
|
|
179
|
+
|
|
180
|
+
请在当前目录下添加 \`.md\` 文件,然后刷新页面。
|
|
181
|
+
|
|
182
|
+
## 文档组织示例
|
|
183
|
+
|
|
184
|
+
\`\`\`
|
|
185
|
+
your-docs/
|
|
186
|
+
├── 00-快速开始.md
|
|
187
|
+
├── 01-功能特性.md
|
|
188
|
+
└── 02-进阶指南/
|
|
189
|
+
├── 01-目录结构.md
|
|
190
|
+
└── 02-自定义配置.md
|
|
191
|
+
\`\`\`
|
|
192
|
+
`)
|
|
193
|
+
}
|
|
194
|
+
|
|
167
195
|
onMounted(async () => {
|
|
168
196
|
await loadDocsList()
|
|
169
|
-
|
|
197
|
+
|
|
198
|
+
// 如果有文档,加载第一个;否则显示提示
|
|
199
|
+
const firstDoc = findFirstDoc(docsList.value)
|
|
200
|
+
if (firstDoc) {
|
|
201
|
+
await loadDoc(firstDoc.key)
|
|
202
|
+
} else {
|
|
203
|
+
showEmptyMessage()
|
|
204
|
+
}
|
|
170
205
|
})
|
|
171
206
|
</script>
|
package/src/api/docs.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { config } from '../config.js'
|
|
2
|
+
|
|
1
3
|
// 构建目录树结构(支持多层嵌套)
|
|
2
4
|
function buildTree(files) {
|
|
3
5
|
const root = { children: [] }
|
|
@@ -23,7 +25,7 @@ function buildTree(files) {
|
|
|
23
25
|
order: match ? parseInt(match[1]) : 999,
|
|
24
26
|
level: i,
|
|
25
27
|
children: [],
|
|
26
|
-
expanded:
|
|
28
|
+
expanded: config.folderExpanded
|
|
27
29
|
}
|
|
28
30
|
currentLevel.children.push(folder)
|
|
29
31
|
}
|
package/src/components/Logo.vue
CHANGED
|
@@ -21,15 +21,15 @@ defineEmits(['go-home'])
|
|
|
21
21
|
gap: 10px;
|
|
22
22
|
color: #111827;
|
|
23
23
|
cursor: pointer;
|
|
24
|
-
transition:
|
|
24
|
+
transition: all 0.15s;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
.logo-container:hover {
|
|
28
|
-
|
|
28
|
+
color: #3eaf7c;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
.logo-container:active {
|
|
32
|
-
|
|
32
|
+
transform: scale(0.96);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
.logo-icon {
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<aside class="toc-sidebar" v-if="tocItems.length > 0 && !collapsed" :style="{ width: width + 'px' }">
|
|
3
3
|
<div class="toc-header">
|
|
4
|
-
<
|
|
5
|
-
|
|
4
|
+
<div class="toc-title">
|
|
5
|
+
<List :size="16" />
|
|
6
|
+
<span>目录</span>
|
|
7
|
+
</div>
|
|
8
|
+
<button class="toc-toggle" @click="$emit('toggle')" title="收起目录">
|
|
9
|
+
<PanelRightClose :size="16" />
|
|
10
|
+
</button>
|
|
6
11
|
</div>
|
|
7
12
|
<nav class="toc-nav">
|
|
8
13
|
<a
|
|
@@ -19,7 +24,7 @@
|
|
|
19
24
|
</template>
|
|
20
25
|
|
|
21
26
|
<script setup>
|
|
22
|
-
import { List } from 'lucide-vue-next'
|
|
27
|
+
import { List, PanelRightClose } from 'lucide-vue-next'
|
|
23
28
|
|
|
24
29
|
defineProps({
|
|
25
30
|
tocItems: {
|
|
@@ -40,5 +45,5 @@ defineProps({
|
|
|
40
45
|
}
|
|
41
46
|
})
|
|
42
47
|
|
|
43
|
-
defineEmits(['scroll-to'])
|
|
48
|
+
defineEmits(['scroll-to', 'toggle'])
|
|
44
49
|
</script>
|
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
:class="{ expanded: item.expanded }"
|
|
8
8
|
:style="{ paddingLeft: `${20 + item.level * 16}px` }"
|
|
9
9
|
@click="$emit('toggle', item)"
|
|
10
|
+
@mouseenter="showTooltip($event, item.label)"
|
|
11
|
+
@mouseleave="hideTooltip"
|
|
10
12
|
>
|
|
11
13
|
<ChevronRight v-if="!item.expanded" class="nav-icon chevron-icon" :size="16" />
|
|
12
14
|
<ChevronDown v-else class="nav-icon chevron-icon" :size="16" />
|
|
13
15
|
<Folder v-if="!item.expanded" class="nav-icon folder-icon" :size="16" />
|
|
14
16
|
<FolderOpen v-else class="nav-icon folder-icon" :size="16" />
|
|
15
|
-
<span>{{ item.label }}</span>
|
|
17
|
+
<span class="nav-label">{{ item.label }}</span>
|
|
16
18
|
</div>
|
|
17
19
|
|
|
18
20
|
<!-- 递归渲染子节点 -->
|
|
@@ -34,9 +36,11 @@
|
|
|
34
36
|
:class="{ active: currentDoc === item.key }"
|
|
35
37
|
:style="{ paddingLeft: `${20 + item.level * 16}px` }"
|
|
36
38
|
@click="$emit('select', item.key)"
|
|
39
|
+
@mouseenter="showTooltip($event, item.label)"
|
|
40
|
+
@mouseleave="hideTooltip"
|
|
37
41
|
>
|
|
38
42
|
<FileText class="nav-icon file-icon" :size="16" />
|
|
39
|
-
<span>{{ item.label }}</span>
|
|
43
|
+
<span class="nav-label">{{ item.label }}</span>
|
|
40
44
|
</div>
|
|
41
45
|
</div>
|
|
42
46
|
</template>
|
|
@@ -56,6 +60,55 @@ defineProps({
|
|
|
56
60
|
})
|
|
57
61
|
|
|
58
62
|
defineEmits(['toggle', 'select'])
|
|
63
|
+
|
|
64
|
+
let tooltipEl = null
|
|
65
|
+
|
|
66
|
+
function showTooltip(event, text) {
|
|
67
|
+
hideTooltip()
|
|
68
|
+
|
|
69
|
+
const target = event.currentTarget
|
|
70
|
+
const label = target.querySelector('.nav-label')
|
|
71
|
+
|
|
72
|
+
// 只有文字被截断时才显示 tooltip
|
|
73
|
+
if (label && label.scrollWidth <= label.clientWidth) return
|
|
74
|
+
|
|
75
|
+
tooltipEl = document.createElement('div')
|
|
76
|
+
tooltipEl.className = 'nav-tooltip'
|
|
77
|
+
tooltipEl.textContent = text
|
|
78
|
+
tooltipEl.style.cssText = `
|
|
79
|
+
position: fixed;
|
|
80
|
+
background: #1f2328;
|
|
81
|
+
color: #fff;
|
|
82
|
+
padding: 6px 10px;
|
|
83
|
+
border-radius: 6px;
|
|
84
|
+
font-size: 12px;
|
|
85
|
+
z-index: 9999;
|
|
86
|
+
max-width: 300px;
|
|
87
|
+
word-break: break-all;
|
|
88
|
+
user-select: text;
|
|
89
|
+
cursor: text;
|
|
90
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
|
91
|
+
`
|
|
92
|
+
|
|
93
|
+
document.body.appendChild(tooltipEl)
|
|
94
|
+
|
|
95
|
+
const rect = target.getBoundingClientRect()
|
|
96
|
+
tooltipEl.style.left = `${rect.right + 8}px`
|
|
97
|
+
tooltipEl.style.top = `${rect.top}px`
|
|
98
|
+
|
|
99
|
+
// 防止超出屏幕右侧
|
|
100
|
+
const tooltipRect = tooltipEl.getBoundingClientRect()
|
|
101
|
+
if (tooltipRect.right > window.innerWidth - 10) {
|
|
102
|
+
tooltipEl.style.left = `${rect.left - tooltipRect.width - 8}px`
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function hideTooltip() {
|
|
107
|
+
if (tooltipEl) {
|
|
108
|
+
tooltipEl.remove()
|
|
109
|
+
tooltipEl = null
|
|
110
|
+
}
|
|
111
|
+
}
|
|
59
112
|
</script>
|
|
60
113
|
|
|
61
114
|
|
package/src/config.js
ADDED
package/src/style.css
CHANGED
|
@@ -5,13 +5,12 @@
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
body {
|
|
8
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "
|
|
9
|
-
line-height: 1.
|
|
10
|
-
color: #
|
|
11
|
-
background: #
|
|
8
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
|
|
9
|
+
line-height: 1.6;
|
|
10
|
+
color: #1f2328;
|
|
11
|
+
background: #ffffff;
|
|
12
12
|
-webkit-font-smoothing: antialiased;
|
|
13
|
-
|
|
14
|
-
font-weight: 400;
|
|
13
|
+
font-size: 16px;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
#app {
|
|
@@ -27,19 +26,59 @@ body {
|
|
|
27
26
|
.sidebar {
|
|
28
27
|
min-width: 200px;
|
|
29
28
|
max-width: 400px;
|
|
30
|
-
background: #
|
|
31
|
-
border-right: 1px solid #
|
|
29
|
+
background: #f6f8fa;
|
|
30
|
+
border-right: 1px solid #d0d7de;
|
|
32
31
|
overflow-y: auto;
|
|
33
32
|
flex-shrink: 0;
|
|
34
|
-
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.02);
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
.logo {
|
|
38
|
-
padding:
|
|
39
|
-
border-bottom: 1px solid #
|
|
40
|
-
|
|
36
|
+
padding: 16px;
|
|
37
|
+
border-bottom: 1px solid #d0d7de;
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
justify-content: space-between;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.logo-group {
|
|
41
44
|
display: flex;
|
|
42
45
|
align-items: center;
|
|
46
|
+
gap: 8px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.github-link {
|
|
50
|
+
display: flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
justify-content: center;
|
|
53
|
+
width: 24px;
|
|
54
|
+
height: 24px;
|
|
55
|
+
color: #ffffff;
|
|
56
|
+
background: #3eaf7c;
|
|
57
|
+
border-radius: 6px;
|
|
58
|
+
transition: all 0.15s;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.github-link:hover {
|
|
62
|
+
background: #2d8a5e;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.sidebar-toggle {
|
|
66
|
+
display: flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
justify-content: center;
|
|
69
|
+
width: 28px;
|
|
70
|
+
height: 28px;
|
|
71
|
+
border: 1px solid #d0d7de;
|
|
72
|
+
background: #ffffff;
|
|
73
|
+
color: #656d76;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
border-radius: 6px;
|
|
76
|
+
transition: all 0.1s;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.sidebar-toggle:hover {
|
|
80
|
+
background: #f6f8fa;
|
|
81
|
+
color: #1f2328;
|
|
43
82
|
}
|
|
44
83
|
|
|
45
84
|
.nav-menu {
|
|
@@ -50,12 +89,12 @@ body {
|
|
|
50
89
|
display: flex;
|
|
51
90
|
align-items: center;
|
|
52
91
|
justify-content: space-between;
|
|
53
|
-
padding:
|
|
54
|
-
font-size:
|
|
55
|
-
color: #
|
|
92
|
+
padding: 12px 16px 8px;
|
|
93
|
+
font-size: 12px;
|
|
94
|
+
color: #656d76;
|
|
56
95
|
font-weight: 600;
|
|
57
96
|
text-transform: uppercase;
|
|
58
|
-
letter-spacing: 0.
|
|
97
|
+
letter-spacing: 0.02em;
|
|
59
98
|
}
|
|
60
99
|
|
|
61
100
|
.nav-actions {
|
|
@@ -67,60 +106,66 @@ body {
|
|
|
67
106
|
display: flex;
|
|
68
107
|
align-items: center;
|
|
69
108
|
justify-content: center;
|
|
70
|
-
width:
|
|
71
|
-
height:
|
|
109
|
+
width: 24px;
|
|
110
|
+
height: 24px;
|
|
72
111
|
border: none;
|
|
73
112
|
background: transparent;
|
|
74
|
-
color: #
|
|
113
|
+
color: #656d76;
|
|
75
114
|
cursor: pointer;
|
|
76
|
-
border-radius:
|
|
77
|
-
transition: all 0.
|
|
115
|
+
border-radius: 6px;
|
|
116
|
+
transition: all 0.1s;
|
|
78
117
|
padding: 0;
|
|
79
118
|
}
|
|
80
119
|
|
|
81
120
|
.action-btn:hover {
|
|
82
|
-
background: #
|
|
83
|
-
color: #
|
|
121
|
+
background: #d0d7de;
|
|
122
|
+
color: #1f2328;
|
|
84
123
|
}
|
|
85
124
|
|
|
86
125
|
.nav-item {
|
|
87
126
|
display: flex;
|
|
88
127
|
align-items: center;
|
|
89
|
-
padding:
|
|
90
|
-
margin: 1px 0;
|
|
128
|
+
padding: 6px 16px;
|
|
91
129
|
cursor: pointer;
|
|
92
|
-
transition: all 0.
|
|
93
|
-
color: #
|
|
94
|
-
font-size:
|
|
95
|
-
border-
|
|
130
|
+
transition: all 0.1s;
|
|
131
|
+
color: #1f2328;
|
|
132
|
+
font-size: 14px;
|
|
133
|
+
border-radius: 6px;
|
|
134
|
+
margin: 1px 8px;
|
|
135
|
+
white-space: nowrap;
|
|
136
|
+
overflow: hidden;
|
|
137
|
+
text-overflow: ellipsis;
|
|
96
138
|
}
|
|
97
139
|
|
|
98
140
|
.nav-item:hover {
|
|
99
|
-
background: #
|
|
100
|
-
color: #1a202c;
|
|
141
|
+
background: #d0d7de;
|
|
101
142
|
}
|
|
102
143
|
|
|
103
144
|
.nav-item.active {
|
|
104
|
-
background: #
|
|
105
|
-
color: #
|
|
145
|
+
background: #e6f7e6;
|
|
146
|
+
color: #3eaf7c;
|
|
106
147
|
font-weight: 500;
|
|
107
|
-
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.nav-label {
|
|
151
|
+
overflow: hidden;
|
|
152
|
+
text-overflow: ellipsis;
|
|
153
|
+
white-space: nowrap;
|
|
108
154
|
}
|
|
109
155
|
|
|
110
156
|
/* 图标样式 */
|
|
111
157
|
.nav-icon {
|
|
112
158
|
flex-shrink: 0;
|
|
113
|
-
margin-right:
|
|
114
|
-
color: #
|
|
115
|
-
transition: all 0.15s;
|
|
159
|
+
margin-right: 8px;
|
|
160
|
+
color: #656d76;
|
|
116
161
|
}
|
|
117
162
|
|
|
118
163
|
.nav-item:hover .nav-icon {
|
|
119
|
-
color: #
|
|
164
|
+
color: #1f2328;
|
|
120
165
|
}
|
|
121
166
|
|
|
122
167
|
.nav-item.active .nav-icon {
|
|
123
|
-
color: #
|
|
168
|
+
color: #3eaf7c;
|
|
124
169
|
}
|
|
125
170
|
|
|
126
171
|
.chevron-icon {
|
|
@@ -128,29 +173,20 @@ body {
|
|
|
128
173
|
}
|
|
129
174
|
|
|
130
175
|
.folder-icon {
|
|
131
|
-
color: #
|
|
176
|
+
color: #3eaf7c;
|
|
132
177
|
}
|
|
133
178
|
|
|
134
179
|
.file-icon {
|
|
135
|
-
color: #
|
|
180
|
+
color: #656d76;
|
|
136
181
|
}
|
|
137
182
|
|
|
138
183
|
.home-icon {
|
|
139
|
-
color: #
|
|
184
|
+
color: #3eaf7c;
|
|
140
185
|
}
|
|
141
186
|
|
|
142
187
|
/* 文件夹样式 */
|
|
143
188
|
.nav-folder {
|
|
144
189
|
font-weight: 500;
|
|
145
|
-
color: #2d3748;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.nav-folder:hover {
|
|
149
|
-
background: #f7fafc;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
.nav-folder:hover .folder-icon {
|
|
153
|
-
color: #dd6b20;
|
|
154
190
|
}
|
|
155
191
|
|
|
156
192
|
/* 多级目录样式 */
|
|
@@ -164,7 +200,6 @@ body {
|
|
|
164
200
|
|
|
165
201
|
.nav-item.level-2 {
|
|
166
202
|
font-size: 13px;
|
|
167
|
-
opacity: 0.9;
|
|
168
203
|
}
|
|
169
204
|
|
|
170
205
|
/* 内容区域样式 */
|
|
@@ -176,308 +211,147 @@ body {
|
|
|
176
211
|
}
|
|
177
212
|
|
|
178
213
|
.markdown-content {
|
|
179
|
-
|
|
214
|
+
width: 90%;
|
|
215
|
+
max-width: none;
|
|
180
216
|
margin: 0 auto;
|
|
181
217
|
background: #ffffff;
|
|
182
|
-
padding:
|
|
218
|
+
padding: 32px 48px;
|
|
183
219
|
}
|
|
184
220
|
|
|
185
221
|
/* Markdown 内容样式 */
|
|
186
222
|
.markdown-content h1 {
|
|
187
223
|
font-size: 32px;
|
|
188
|
-
margin-bottom:
|
|
189
|
-
padding-bottom:
|
|
190
|
-
border-bottom:
|
|
191
|
-
color: #
|
|
192
|
-
font-weight:
|
|
193
|
-
letter-spacing: -0.02em;
|
|
224
|
+
margin-bottom: 16px;
|
|
225
|
+
padding-bottom: 8px;
|
|
226
|
+
border-bottom: 1px solid #d0d7de;
|
|
227
|
+
color: #1f2328;
|
|
228
|
+
font-weight: 600;
|
|
194
229
|
line-height: 1.25;
|
|
195
230
|
}
|
|
196
231
|
|
|
197
232
|
.markdown-content h2 {
|
|
198
233
|
font-size: 24px;
|
|
199
|
-
margin-top:
|
|
200
|
-
margin-bottom:
|
|
201
|
-
|
|
234
|
+
margin-top: 32px;
|
|
235
|
+
margin-bottom: 16px;
|
|
236
|
+
padding-bottom: 8px;
|
|
237
|
+
border-bottom: 1px solid #d0d7de;
|
|
238
|
+
color: #1f2328;
|
|
202
239
|
font-weight: 600;
|
|
203
|
-
|
|
204
|
-
line-height: 1.35;
|
|
240
|
+
line-height: 1.25;
|
|
205
241
|
}
|
|
206
242
|
|
|
207
243
|
.markdown-content h3 {
|
|
208
|
-
font-size:
|
|
209
|
-
margin-top:
|
|
244
|
+
font-size: 20px;
|
|
245
|
+
margin-top: 24px;
|
|
210
246
|
margin-bottom: 16px;
|
|
211
|
-
color: #
|
|
247
|
+
color: #1f2328;
|
|
212
248
|
font-weight: 600;
|
|
213
|
-
line-height: 1.
|
|
249
|
+
line-height: 1.25;
|
|
214
250
|
}
|
|
215
251
|
|
|
216
252
|
.markdown-content h4 {
|
|
217
253
|
font-size: 16px;
|
|
218
|
-
margin-top:
|
|
219
|
-
margin-bottom:
|
|
220
|
-
color: #
|
|
254
|
+
margin-top: 24px;
|
|
255
|
+
margin-bottom: 16px;
|
|
256
|
+
color: #1f2328;
|
|
221
257
|
font-weight: 600;
|
|
222
258
|
}
|
|
223
259
|
|
|
224
260
|
.markdown-content p {
|
|
225
|
-
margin-bottom:
|
|
226
|
-
color: #
|
|
227
|
-
font-size: 15px;
|
|
228
|
-
line-height: 1.75;
|
|
261
|
+
margin-bottom: 16px;
|
|
262
|
+
color: #1f2328;
|
|
229
263
|
}
|
|
230
264
|
|
|
231
265
|
.markdown-content ul,
|
|
232
266
|
.markdown-content ol {
|
|
233
|
-
margin-bottom:
|
|
234
|
-
padding-left:
|
|
267
|
+
margin-bottom: 16px;
|
|
268
|
+
padding-left: 2em;
|
|
235
269
|
}
|
|
236
270
|
|
|
237
271
|
.markdown-content li {
|
|
238
|
-
margin-bottom:
|
|
239
|
-
color: #
|
|
240
|
-
font-size: 15px;
|
|
241
|
-
line-height: 1.75;
|
|
272
|
+
margin-bottom: 4px;
|
|
273
|
+
color: #1f2328;
|
|
242
274
|
}
|
|
243
275
|
|
|
244
276
|
.markdown-content code {
|
|
245
|
-
background:
|
|
246
|
-
padding:
|
|
247
|
-
border-radius:
|
|
248
|
-
font-family: "SF Mono",
|
|
249
|
-
font-size:
|
|
250
|
-
color: #
|
|
251
|
-
border: 1px solid #fecaca;
|
|
252
|
-
font-weight: 500;
|
|
277
|
+
background: rgba(175, 184, 193, 0.2);
|
|
278
|
+
padding: 0.2em 0.4em;
|
|
279
|
+
border-radius: 6px;
|
|
280
|
+
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
|
281
|
+
font-size: 85%;
|
|
282
|
+
color: #1f2328;
|
|
253
283
|
}
|
|
254
284
|
|
|
255
285
|
.markdown-content pre {
|
|
256
|
-
background: #
|
|
257
|
-
padding:
|
|
286
|
+
background: #24292f;
|
|
287
|
+
padding: 16px;
|
|
258
288
|
border-radius: 6px;
|
|
259
289
|
overflow-x: auto;
|
|
260
|
-
margin-bottom:
|
|
261
|
-
border: 1px solid #2d2d2d;
|
|
262
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
290
|
+
margin-bottom: 16px;
|
|
263
291
|
}
|
|
264
292
|
|
|
265
293
|
.markdown-content pre code {
|
|
266
294
|
background: none;
|
|
267
|
-
color: #
|
|
295
|
+
color: #e6edf3;
|
|
268
296
|
padding: 0;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
line-height: 1.7;
|
|
272
|
-
display: block;
|
|
273
|
-
font-weight: 400;
|
|
297
|
+
font-size: 85%;
|
|
298
|
+
line-height: 1.45;
|
|
274
299
|
}
|
|
275
300
|
|
|
276
301
|
.markdown-content a {
|
|
277
|
-
color: #
|
|
278
|
-
text-decoration:
|
|
279
|
-
text-decoration-color: #90cdf4;
|
|
280
|
-
text-underline-offset: 2px;
|
|
281
|
-
transition: all 0.15s;
|
|
282
|
-
font-weight: 500;
|
|
302
|
+
color: #3eaf7c;
|
|
303
|
+
text-decoration: none;
|
|
283
304
|
}
|
|
284
305
|
|
|
285
306
|
.markdown-content a:hover {
|
|
286
|
-
|
|
287
|
-
text-decoration-color: #3182ce;
|
|
307
|
+
text-decoration: underline;
|
|
288
308
|
}
|
|
289
309
|
|
|
290
|
-
/*
|
|
310
|
+
/* 表格样式 */
|
|
291
311
|
.markdown-content .table-wrapper {
|
|
292
312
|
width: 100%;
|
|
293
313
|
overflow-x: auto;
|
|
294
|
-
margin-bottom:
|
|
295
|
-
border-radius: 8px;
|
|
296
|
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
|
314
|
+
margin-bottom: 16px;
|
|
297
315
|
}
|
|
298
316
|
|
|
299
317
|
.markdown-content table {
|
|
300
318
|
width: 100%;
|
|
301
319
|
border-collapse: collapse;
|
|
302
|
-
|
|
303
|
-
border: 1px solid #cbd5e0;
|
|
304
|
-
font-size: 14px;
|
|
305
|
-
border-radius: 8px;
|
|
306
|
-
overflow: hidden;
|
|
307
|
-
table-layout: auto;
|
|
308
|
-
background: #ffffff;
|
|
320
|
+
border-spacing: 0;
|
|
309
321
|
}
|
|
310
322
|
|
|
311
323
|
.markdown-content table th,
|
|
312
324
|
.markdown-content table td {
|
|
313
|
-
border: 1px solid #
|
|
314
|
-
padding:
|
|
315
|
-
text-align: left;
|
|
316
|
-
vertical-align: top;
|
|
317
|
-
word-wrap: break-word;
|
|
318
|
-
word-break: break-word;
|
|
319
|
-
min-width: 100px;
|
|
320
|
-
line-height: 1.6;
|
|
325
|
+
border: 1px solid #d0d7de;
|
|
326
|
+
padding: 6px 13px;
|
|
321
327
|
}
|
|
322
328
|
|
|
323
329
|
.markdown-content table th {
|
|
324
|
-
background:
|
|
325
|
-
font-weight: 600;
|
|
326
|
-
color: #2d3748;
|
|
327
|
-
font-size: 13px;
|
|
328
|
-
letter-spacing: 0.02em;
|
|
329
|
-
white-space: nowrap;
|
|
330
|
-
border-bottom: 2px solid #cbd5e0;
|
|
331
|
-
position: sticky;
|
|
332
|
-
top: 0;
|
|
333
|
-
z-index: 10;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/* 第一列(表A)适中宽度 */
|
|
337
|
-
.markdown-content table th:first-child,
|
|
338
|
-
.markdown-content table td:first-child {
|
|
339
|
-
width: 15%;
|
|
340
|
-
min-width: 140px;
|
|
341
|
-
font-weight: 500;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/* 第二列(关系类型)窄一些 */
|
|
345
|
-
.markdown-content table th:nth-child(2),
|
|
346
|
-
.markdown-content table td:nth-child(2) {
|
|
347
|
-
width: 8%;
|
|
348
|
-
min-width: 70px;
|
|
349
|
-
text-align: center;
|
|
350
|
-
font-weight: 500;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/* 第三列(表B)适中宽度 */
|
|
354
|
-
.markdown-content table th:nth-child(3),
|
|
355
|
-
.markdown-content table td:nth-child(3) {
|
|
356
|
-
width: 15%;
|
|
357
|
-
min-width: 140px;
|
|
358
|
-
font-weight: 500;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/* 第四列(关联字段)较宽 */
|
|
362
|
-
.markdown-content table th:nth-child(4),
|
|
363
|
-
.markdown-content table td:nth-child(4) {
|
|
364
|
-
width: 22%;
|
|
365
|
-
min-width: 180px;
|
|
366
|
-
font-family: "SF Mono", "Consolas", "Monaco", monospace;
|
|
367
|
-
font-size: 13px;
|
|
368
|
-
color: #4a5568;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/* 最后一列(说明)最宽,自动填充剩余空间 */
|
|
372
|
-
.markdown-content table th:last-child,
|
|
373
|
-
.markdown-content table td:last-child {
|
|
374
|
-
width: 40%;
|
|
375
|
-
min-width: 220px;
|
|
376
|
-
color: #4a5568;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
.markdown-content table tbody tr {
|
|
380
|
-
transition: all 0.15s ease;
|
|
381
|
-
border-bottom: 1px solid #f1f5f9;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
.markdown-content table tbody tr:hover {
|
|
385
|
-
background-color: #f8fafc;
|
|
386
|
-
box-shadow: inset 0 0 0 1px #e2e8f0;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
.markdown-content table tbody tr:last-child {
|
|
390
|
-
border-bottom: none;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/* 字段名样式 */
|
|
394
|
-
.markdown-content table .field-name-cell {
|
|
395
|
-
font-family: "SF Mono", "Consolas", "Monaco", monospace;
|
|
396
|
-
color: #dc2626;
|
|
397
|
-
font-weight: 500;
|
|
398
|
-
font-size: 13px;
|
|
399
|
-
background-color: #fef2f2;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/* 必填标记样式 */
|
|
403
|
-
.markdown-content table .required-yes {
|
|
404
|
-
color: #2d3748;
|
|
330
|
+
background: #f6f8fa;
|
|
405
331
|
font-weight: 600;
|
|
406
|
-
text-align: center;
|
|
407
332
|
}
|
|
408
333
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
height: 8px;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
.markdown-content .table-wrapper::-webkit-scrollbar-track {
|
|
415
|
-
background: #f1f5f9;
|
|
416
|
-
border-radius: 4px;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
.markdown-content .table-wrapper::-webkit-scrollbar-thumb {
|
|
420
|
-
background: #cbd5e0;
|
|
421
|
-
border-radius: 4px;
|
|
422
|
-
transition: background 0.2s;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
.markdown-content .table-wrapper::-webkit-scrollbar-thumb:hover {
|
|
426
|
-
background: #94a3b8;
|
|
334
|
+
.markdown-content table tr:nth-child(2n) {
|
|
335
|
+
background: #f6f8fa;
|
|
427
336
|
}
|
|
428
337
|
|
|
429
338
|
.markdown-content blockquote {
|
|
430
|
-
border-left:
|
|
431
|
-
padding
|
|
432
|
-
margin:
|
|
433
|
-
color: #
|
|
434
|
-
font-style: italic;
|
|
435
|
-
background: #ebf8ff;
|
|
436
|
-
padding: 16px 20px;
|
|
437
|
-
border-radius: 4px;
|
|
339
|
+
border-left: 4px solid #d0d7de;
|
|
340
|
+
padding: 0 16px;
|
|
341
|
+
margin: 0 0 16px;
|
|
342
|
+
color: #656d76;
|
|
438
343
|
}
|
|
439
344
|
|
|
440
345
|
.markdown-content img {
|
|
441
346
|
max-width: 100%;
|
|
442
347
|
height: auto;
|
|
443
|
-
border-radius:
|
|
444
|
-
margin:
|
|
445
|
-
transition: all 0.2s ease;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
.markdown-content img:hover {
|
|
449
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
450
|
-
transform: translateY(-2px);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/* 可放大图片样式 */
|
|
454
|
-
.zoomable-image {
|
|
455
|
-
cursor: zoom-in !important;
|
|
456
|
-
position: relative;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
.zoomable-image::after {
|
|
460
|
-
content: '🔍';
|
|
461
|
-
position: absolute;
|
|
462
|
-
top: 8px;
|
|
463
|
-
right: 8px;
|
|
464
|
-
background: rgba(0, 0, 0, 0.7);
|
|
465
|
-
color: white;
|
|
466
|
-
padding: 4px 8px;
|
|
467
|
-
border-radius: 4px;
|
|
468
|
-
font-size: 12px;
|
|
469
|
-
opacity: 0;
|
|
470
|
-
transition: opacity 0.2s ease;
|
|
471
|
-
pointer-events: none;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
.zoomable-image:hover::after {
|
|
475
|
-
opacity: 1;
|
|
348
|
+
border-radius: 6px;
|
|
349
|
+
margin: 8px 0;
|
|
476
350
|
}
|
|
477
351
|
|
|
478
352
|
/* Mermaid 图表样式 */
|
|
479
353
|
.markdown-content .mermaid {
|
|
480
|
-
margin:
|
|
354
|
+
margin: 16px 0;
|
|
481
355
|
text-align: center;
|
|
482
356
|
}
|
|
483
357
|
|
|
@@ -487,189 +361,167 @@ body {
|
|
|
487
361
|
}
|
|
488
362
|
|
|
489
363
|
.markdown-content .mermaid-error {
|
|
490
|
-
color: #
|
|
491
|
-
background: #
|
|
364
|
+
color: #cf222e;
|
|
365
|
+
background: #ffebe9;
|
|
492
366
|
padding: 12px;
|
|
493
|
-
border-radius:
|
|
494
|
-
border: 1px solid #
|
|
495
|
-
font-size: 14px;
|
|
367
|
+
border-radius: 6px;
|
|
368
|
+
border: 1px solid #ff8182;
|
|
496
369
|
}
|
|
497
370
|
|
|
498
371
|
/* 滚动条样式 */
|
|
499
372
|
.sidebar::-webkit-scrollbar,
|
|
500
373
|
.content::-webkit-scrollbar {
|
|
501
|
-
width:
|
|
374
|
+
width: 8px;
|
|
502
375
|
}
|
|
503
376
|
|
|
504
377
|
.sidebar::-webkit-scrollbar-thumb,
|
|
505
378
|
.content::-webkit-scrollbar-thumb {
|
|
506
|
-
background: #
|
|
507
|
-
border-radius:
|
|
379
|
+
background: #d0d7de;
|
|
380
|
+
border-radius: 4px;
|
|
508
381
|
}
|
|
509
382
|
|
|
510
383
|
.sidebar::-webkit-scrollbar-thumb:hover,
|
|
511
384
|
.content::-webkit-scrollbar-thumb:hover {
|
|
512
|
-
background: #
|
|
385
|
+
background: #afb8c1;
|
|
513
386
|
}
|
|
514
387
|
|
|
515
388
|
/* 返回顶部按钮 */
|
|
516
389
|
.back-to-top {
|
|
517
390
|
position: fixed;
|
|
518
|
-
right:
|
|
519
|
-
bottom:
|
|
520
|
-
width:
|
|
521
|
-
height:
|
|
391
|
+
right: 24px;
|
|
392
|
+
bottom: 24px;
|
|
393
|
+
width: 48px;
|
|
394
|
+
height: 48px;
|
|
522
395
|
display: flex;
|
|
523
396
|
flex-direction: column;
|
|
524
397
|
align-items: center;
|
|
525
398
|
justify-content: center;
|
|
526
|
-
gap:
|
|
399
|
+
gap: 2px;
|
|
527
400
|
background: #ffffff;
|
|
528
|
-
color: #
|
|
529
|
-
border: 1px solid #
|
|
530
|
-
border-radius:
|
|
401
|
+
color: #656d76;
|
|
402
|
+
border: 1px solid #d0d7de;
|
|
403
|
+
border-radius: 6px;
|
|
531
404
|
cursor: pointer;
|
|
532
|
-
box-shadow: 0
|
|
533
|
-
transition: all 0.
|
|
405
|
+
box-shadow: 0 1px 3px rgba(31, 35, 40, 0.12);
|
|
406
|
+
transition: all 0.1s;
|
|
534
407
|
z-index: 1000;
|
|
535
408
|
}
|
|
536
409
|
|
|
537
410
|
.back-to-top:hover {
|
|
538
|
-
background: #
|
|
539
|
-
color: #
|
|
540
|
-
border-color: #
|
|
541
|
-
box-shadow: 0 6px 16px rgba(49, 130, 206, 0.3);
|
|
542
|
-
transform: translateY(-2px);
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
.back-to-top:active {
|
|
546
|
-
transform: translateY(0) scale(0.95);
|
|
411
|
+
background: #e6f7e6;
|
|
412
|
+
color: #3eaf7c;
|
|
413
|
+
border-color: #3eaf7c;
|
|
547
414
|
}
|
|
548
415
|
|
|
549
416
|
.progress-text {
|
|
550
|
-
font-size:
|
|
551
|
-
font-weight:
|
|
552
|
-
line-height: 1;
|
|
553
|
-
color: inherit;
|
|
417
|
+
font-size: 12px;
|
|
418
|
+
font-weight: 500;
|
|
554
419
|
}
|
|
555
420
|
|
|
556
421
|
/* 淡入淡出动画 */
|
|
557
422
|
.fade-enter-active,
|
|
558
423
|
.fade-leave-active {
|
|
559
|
-
transition: opacity 0.
|
|
424
|
+
transition: opacity 0.2s;
|
|
560
425
|
}
|
|
561
426
|
|
|
562
427
|
.fade-enter-from,
|
|
563
428
|
.fade-leave-to {
|
|
564
429
|
opacity: 0;
|
|
565
|
-
transform: translateY(10px);
|
|
566
430
|
}
|
|
567
431
|
|
|
568
432
|
/* 右侧目录样式 */
|
|
569
433
|
.toc-sidebar {
|
|
570
434
|
min-width: 200px;
|
|
571
|
-
max-width:
|
|
435
|
+
max-width: 300px;
|
|
572
436
|
background: #ffffff;
|
|
573
|
-
border-left: 1px solid #
|
|
437
|
+
border-left: 1px solid #d0d7de;
|
|
574
438
|
overflow-y: auto;
|
|
575
439
|
flex-shrink: 0;
|
|
576
|
-
padding:
|
|
577
|
-
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.02);
|
|
440
|
+
padding: 32px 0;
|
|
578
441
|
}
|
|
579
442
|
|
|
580
443
|
.toc-header {
|
|
444
|
+
display: flex;
|
|
445
|
+
align-items: center;
|
|
446
|
+
justify-content: space-between;
|
|
447
|
+
padding: 0 16px 12px;
|
|
448
|
+
border-bottom: 1px solid #d0d7de;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.toc-title {
|
|
581
452
|
display: flex;
|
|
582
453
|
align-items: center;
|
|
583
454
|
gap: 8px;
|
|
584
|
-
|
|
585
|
-
font-size: 11px;
|
|
455
|
+
font-size: 12px;
|
|
586
456
|
font-weight: 600;
|
|
587
|
-
color: #
|
|
588
|
-
border-bottom: 1px solid #e2e8f0;
|
|
589
|
-
letter-spacing: 0.05em;
|
|
457
|
+
color: #1f2328;
|
|
590
458
|
text-transform: uppercase;
|
|
459
|
+
letter-spacing: 0.02em;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.toc-toggle {
|
|
463
|
+
display: flex;
|
|
464
|
+
align-items: center;
|
|
465
|
+
justify-content: center;
|
|
466
|
+
width: 28px;
|
|
467
|
+
height: 28px;
|
|
468
|
+
border: 1px solid #d0d7de;
|
|
469
|
+
background: #ffffff;
|
|
470
|
+
color: #656d76;
|
|
471
|
+
cursor: pointer;
|
|
472
|
+
border-radius: 6px;
|
|
473
|
+
transition: all 0.1s;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.toc-toggle:hover {
|
|
477
|
+
background: #f6f8fa;
|
|
478
|
+
color: #1f2328;
|
|
591
479
|
}
|
|
592
480
|
|
|
593
481
|
.toc-nav {
|
|
594
|
-
padding:
|
|
482
|
+
padding: 12px 0;
|
|
595
483
|
}
|
|
596
484
|
|
|
597
485
|
.toc-item {
|
|
598
486
|
display: block;
|
|
599
|
-
padding:
|
|
600
|
-
color: #
|
|
487
|
+
padding: 4px 16px;
|
|
488
|
+
color: #656d76;
|
|
601
489
|
text-decoration: none;
|
|
602
490
|
font-size: 12px;
|
|
603
|
-
line-height: 1.
|
|
604
|
-
transition: all 0.
|
|
491
|
+
line-height: 1.5;
|
|
492
|
+
transition: all 0.1s;
|
|
605
493
|
border-left: 2px solid transparent;
|
|
606
|
-
overflow: hidden;
|
|
607
|
-
text-overflow: ellipsis;
|
|
608
|
-
white-space: nowrap;
|
|
609
494
|
}
|
|
610
495
|
|
|
611
496
|
.toc-item:hover {
|
|
612
|
-
color: #
|
|
613
|
-
background: #f7fafc;
|
|
497
|
+
color: #3eaf7c;
|
|
614
498
|
}
|
|
615
499
|
|
|
616
500
|
.toc-item.active {
|
|
617
|
-
color: #
|
|
618
|
-
border-left-color: #
|
|
501
|
+
color: #3eaf7c;
|
|
502
|
+
border-left-color: #3eaf7c;
|
|
619
503
|
font-weight: 500;
|
|
620
|
-
background: #ebf8ff;
|
|
621
504
|
}
|
|
622
505
|
|
|
623
|
-
/* 不同层级的缩进 */
|
|
624
506
|
.toc-item.toc-level-1 {
|
|
625
|
-
padding-left:
|
|
626
|
-
font-size: 13px;
|
|
507
|
+
padding-left: 16px;
|
|
627
508
|
font-weight: 500;
|
|
628
|
-
color: #
|
|
629
|
-
margin-top:
|
|
509
|
+
color: #1f2328;
|
|
510
|
+
margin-top: 8px;
|
|
630
511
|
}
|
|
631
512
|
|
|
632
513
|
.toc-item.toc-level-2 {
|
|
633
|
-
padding-left:
|
|
634
|
-
font-size: 12px;
|
|
635
|
-
margin-top: 2px;
|
|
514
|
+
padding-left: 24px;
|
|
636
515
|
}
|
|
637
516
|
|
|
638
517
|
.toc-item.toc-level-3 {
|
|
639
|
-
padding-left:
|
|
518
|
+
padding-left: 32px;
|
|
640
519
|
font-size: 11px;
|
|
641
520
|
}
|
|
642
521
|
|
|
643
522
|
.toc-item.toc-level-4 {
|
|
644
|
-
padding-left:
|
|
645
|
-
font-size: 12px;
|
|
646
|
-
opacity: 0.9;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
.toc-item.toc-level-5 {
|
|
650
|
-
padding-left: 68px;
|
|
651
|
-
font-size: 11px;
|
|
652
|
-
opacity: 0.85;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
.toc-item.toc-level-6 {
|
|
656
|
-
padding-left: 80px;
|
|
523
|
+
padding-left: 40px;
|
|
657
524
|
font-size: 11px;
|
|
658
|
-
opacity: 0.8;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
/* 目录滚动条样式 */
|
|
662
|
-
.toc-sidebar::-webkit-scrollbar {
|
|
663
|
-
width: 6px;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
.toc-sidebar::-webkit-scrollbar-thumb {
|
|
667
|
-
background: #dcdfe6;
|
|
668
|
-
border-radius: 3px;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
.toc-sidebar::-webkit-scrollbar-thumb:hover {
|
|
672
|
-
background: #c0c4cc;
|
|
673
525
|
}
|
|
674
526
|
|
|
675
527
|
/* 拖拽条样式 */
|
|
@@ -678,40 +530,22 @@ body {
|
|
|
678
530
|
background: transparent;
|
|
679
531
|
cursor: col-resize;
|
|
680
532
|
flex-shrink: 0;
|
|
681
|
-
|
|
682
|
-
transition: background 0.15s;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
.resizer::before {
|
|
686
|
-
content: '';
|
|
687
|
-
position: absolute;
|
|
688
|
-
top: 0;
|
|
689
|
-
bottom: 0;
|
|
690
|
-
left: -2px;
|
|
691
|
-
right: -2px;
|
|
533
|
+
transition: background 0.1s;
|
|
692
534
|
}
|
|
693
535
|
|
|
694
536
|
.resizer:hover {
|
|
695
|
-
background: #
|
|
537
|
+
background: #d0d7de;
|
|
696
538
|
}
|
|
697
539
|
|
|
698
540
|
.resizer:active {
|
|
699
|
-
background: #
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
.resizer-left {
|
|
703
|
-
margin-left: -1px;
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
.resizer-right {
|
|
707
|
-
margin-right: -1px;
|
|
541
|
+
background: #3eaf7c;
|
|
708
542
|
}
|
|
709
543
|
|
|
710
544
|
/* 收起/展开按钮 */
|
|
711
545
|
.collapse-btn,
|
|
712
546
|
.expand-btn {
|
|
713
547
|
position: fixed;
|
|
714
|
-
top:
|
|
548
|
+
top: 16px;
|
|
715
549
|
z-index: 100;
|
|
716
550
|
width: 32px;
|
|
717
551
|
height: 32px;
|
|
@@ -719,30 +553,21 @@ body {
|
|
|
719
553
|
align-items: center;
|
|
720
554
|
justify-content: center;
|
|
721
555
|
background: #ffffff;
|
|
722
|
-
border: 1px solid #
|
|
556
|
+
border: 1px solid #d0d7de;
|
|
723
557
|
border-radius: 6px;
|
|
724
558
|
cursor: pointer;
|
|
725
|
-
color: #
|
|
726
|
-
transition: all 0.
|
|
727
|
-
box-shadow: 0
|
|
559
|
+
color: #656d76;
|
|
560
|
+
transition: all 0.1s;
|
|
561
|
+
box-shadow: 0 1px 3px rgba(31, 35, 40, 0.12);
|
|
728
562
|
}
|
|
729
563
|
|
|
730
564
|
.collapse-btn:hover,
|
|
731
565
|
.expand-btn:hover {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
box-shadow: 0 4px 12px rgba(49, 130, 206, 0.15);
|
|
735
|
-
transform: translateY(-1px);
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
.collapse-btn-left {
|
|
739
|
-
left: 16px;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
.collapse-btn-right {
|
|
743
|
-
right: 16px;
|
|
566
|
+
background: #f6f8fa;
|
|
567
|
+
color: #1f2328;
|
|
744
568
|
}
|
|
745
569
|
|
|
570
|
+
.collapse-btn-left,
|
|
746
571
|
.expand-btn-left {
|
|
747
572
|
left: 16px;
|
|
748
573
|
}
|
|
@@ -767,18 +592,14 @@ body {
|
|
|
767
592
|
width: 240px;
|
|
768
593
|
}
|
|
769
594
|
|
|
770
|
-
.content {
|
|
771
|
-
padding: 20px;
|
|
772
|
-
}
|
|
773
|
-
|
|
774
595
|
.markdown-content {
|
|
775
|
-
padding:
|
|
596
|
+
padding: 16px;
|
|
776
597
|
}
|
|
777
598
|
|
|
778
599
|
.back-to-top {
|
|
779
|
-
right:
|
|
780
|
-
bottom:
|
|
781
|
-
width:
|
|
782
|
-
height:
|
|
600
|
+
right: 16px;
|
|
601
|
+
bottom: 16px;
|
|
602
|
+
width: 40px;
|
|
603
|
+
height: 40px;
|
|
783
604
|
}
|
|
784
|
-
}
|
|
605
|
+
}
|
package/vite.config.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { defineConfig } from 'vite'
|
|
2
2
|
import vue from '@vitejs/plugin-vue'
|
|
3
|
+
import { config } from './src/config.js'
|
|
3
4
|
|
|
4
5
|
export default defineConfig({
|
|
5
6
|
plugins: [vue()],
|
|
6
7
|
server: {
|
|
7
|
-
port:
|
|
8
|
+
port: config.defaultPort
|
|
8
9
|
},
|
|
9
10
|
optimizeDeps: {
|
|
10
11
|
include: ['vue', 'marked', 'mermaid']
|