md2ui 1.0.2 → 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 +230 -410
- 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
|
/* 内容区域样式 */
|
|
@@ -180,305 +215,143 @@ body {
|
|
|
180
215
|
max-width: none;
|
|
181
216
|
margin: 0 auto;
|
|
182
217
|
background: #ffffff;
|
|
183
|
-
padding:
|
|
218
|
+
padding: 32px 48px;
|
|
184
219
|
}
|
|
185
220
|
|
|
186
221
|
/* Markdown 内容样式 */
|
|
187
222
|
.markdown-content h1 {
|
|
188
223
|
font-size: 32px;
|
|
189
|
-
margin-bottom:
|
|
190
|
-
padding-bottom:
|
|
191
|
-
border-bottom:
|
|
192
|
-
color: #
|
|
193
|
-
font-weight:
|
|
194
|
-
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;
|
|
195
229
|
line-height: 1.25;
|
|
196
230
|
}
|
|
197
231
|
|
|
198
232
|
.markdown-content h2 {
|
|
199
233
|
font-size: 24px;
|
|
200
|
-
margin-top:
|
|
201
|
-
margin-bottom:
|
|
202
|
-
|
|
234
|
+
margin-top: 32px;
|
|
235
|
+
margin-bottom: 16px;
|
|
236
|
+
padding-bottom: 8px;
|
|
237
|
+
border-bottom: 1px solid #d0d7de;
|
|
238
|
+
color: #1f2328;
|
|
203
239
|
font-weight: 600;
|
|
204
|
-
|
|
205
|
-
line-height: 1.35;
|
|
240
|
+
line-height: 1.25;
|
|
206
241
|
}
|
|
207
242
|
|
|
208
243
|
.markdown-content h3 {
|
|
209
|
-
font-size:
|
|
210
|
-
margin-top:
|
|
244
|
+
font-size: 20px;
|
|
245
|
+
margin-top: 24px;
|
|
211
246
|
margin-bottom: 16px;
|
|
212
|
-
color: #
|
|
247
|
+
color: #1f2328;
|
|
213
248
|
font-weight: 600;
|
|
214
|
-
line-height: 1.
|
|
249
|
+
line-height: 1.25;
|
|
215
250
|
}
|
|
216
251
|
|
|
217
252
|
.markdown-content h4 {
|
|
218
253
|
font-size: 16px;
|
|
219
|
-
margin-top:
|
|
220
|
-
margin-bottom:
|
|
221
|
-
color: #
|
|
254
|
+
margin-top: 24px;
|
|
255
|
+
margin-bottom: 16px;
|
|
256
|
+
color: #1f2328;
|
|
222
257
|
font-weight: 600;
|
|
223
258
|
}
|
|
224
259
|
|
|
225
260
|
.markdown-content p {
|
|
226
|
-
margin-bottom:
|
|
227
|
-
color: #
|
|
228
|
-
font-size: 15px;
|
|
229
|
-
line-height: 1.75;
|
|
261
|
+
margin-bottom: 16px;
|
|
262
|
+
color: #1f2328;
|
|
230
263
|
}
|
|
231
264
|
|
|
232
265
|
.markdown-content ul,
|
|
233
266
|
.markdown-content ol {
|
|
234
|
-
margin-bottom:
|
|
235
|
-
padding-left:
|
|
267
|
+
margin-bottom: 16px;
|
|
268
|
+
padding-left: 2em;
|
|
236
269
|
}
|
|
237
270
|
|
|
238
271
|
.markdown-content li {
|
|
239
|
-
margin-bottom:
|
|
240
|
-
color: #
|
|
241
|
-
font-size: 15px;
|
|
242
|
-
line-height: 1.75;
|
|
272
|
+
margin-bottom: 4px;
|
|
273
|
+
color: #1f2328;
|
|
243
274
|
}
|
|
244
275
|
|
|
245
276
|
.markdown-content code {
|
|
246
|
-
background:
|
|
247
|
-
padding:
|
|
248
|
-
border-radius:
|
|
249
|
-
font-family: "SF Mono",
|
|
250
|
-
font-size:
|
|
251
|
-
color: #
|
|
252
|
-
border: 1px solid #fecaca;
|
|
253
|
-
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;
|
|
254
283
|
}
|
|
255
284
|
|
|
256
285
|
.markdown-content pre {
|
|
257
|
-
background: #
|
|
258
|
-
padding:
|
|
286
|
+
background: #24292f;
|
|
287
|
+
padding: 16px;
|
|
259
288
|
border-radius: 6px;
|
|
260
289
|
overflow-x: auto;
|
|
261
|
-
margin-bottom:
|
|
262
|
-
border: 1px solid #2d2d2d;
|
|
263
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
290
|
+
margin-bottom: 16px;
|
|
264
291
|
}
|
|
265
292
|
|
|
266
293
|
.markdown-content pre code {
|
|
267
294
|
background: none;
|
|
268
|
-
color: #
|
|
295
|
+
color: #e6edf3;
|
|
269
296
|
padding: 0;
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
line-height: 1.7;
|
|
273
|
-
display: block;
|
|
274
|
-
font-weight: 400;
|
|
297
|
+
font-size: 85%;
|
|
298
|
+
line-height: 1.45;
|
|
275
299
|
}
|
|
276
300
|
|
|
277
301
|
.markdown-content a {
|
|
278
|
-
color: #
|
|
279
|
-
text-decoration:
|
|
280
|
-
text-decoration-color: #90cdf4;
|
|
281
|
-
text-underline-offset: 2px;
|
|
282
|
-
transition: all 0.15s;
|
|
283
|
-
font-weight: 500;
|
|
302
|
+
color: #3eaf7c;
|
|
303
|
+
text-decoration: none;
|
|
284
304
|
}
|
|
285
305
|
|
|
286
306
|
.markdown-content a:hover {
|
|
287
|
-
|
|
288
|
-
text-decoration-color: #3182ce;
|
|
307
|
+
text-decoration: underline;
|
|
289
308
|
}
|
|
290
309
|
|
|
291
|
-
/*
|
|
310
|
+
/* 表格样式 */
|
|
292
311
|
.markdown-content .table-wrapper {
|
|
293
312
|
width: 100%;
|
|
294
313
|
overflow-x: auto;
|
|
295
|
-
margin-bottom:
|
|
296
|
-
border-radius: 8px;
|
|
297
|
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
|
314
|
+
margin-bottom: 16px;
|
|
298
315
|
}
|
|
299
316
|
|
|
300
317
|
.markdown-content table {
|
|
301
318
|
width: 100%;
|
|
302
319
|
border-collapse: collapse;
|
|
303
|
-
|
|
304
|
-
border: 1px solid #cbd5e0;
|
|
305
|
-
font-size: 14px;
|
|
306
|
-
border-radius: 8px;
|
|
307
|
-
overflow: hidden;
|
|
308
|
-
table-layout: auto;
|
|
309
|
-
background: #ffffff;
|
|
320
|
+
border-spacing: 0;
|
|
310
321
|
}
|
|
311
322
|
|
|
312
323
|
.markdown-content table th,
|
|
313
324
|
.markdown-content table td {
|
|
314
|
-
border: 1px solid #
|
|
315
|
-
padding:
|
|
316
|
-
text-align: left;
|
|
317
|
-
vertical-align: top;
|
|
318
|
-
word-wrap: break-word;
|
|
319
|
-
word-break: break-word;
|
|
320
|
-
min-width: 100px;
|
|
321
|
-
line-height: 1.6;
|
|
325
|
+
border: 1px solid #d0d7de;
|
|
326
|
+
padding: 6px 13px;
|
|
322
327
|
}
|
|
323
328
|
|
|
324
329
|
.markdown-content table th {
|
|
325
|
-
background:
|
|
326
|
-
font-weight: 600;
|
|
327
|
-
color: #2d3748;
|
|
328
|
-
font-size: 13px;
|
|
329
|
-
letter-spacing: 0.02em;
|
|
330
|
-
white-space: nowrap;
|
|
331
|
-
border-bottom: 2px solid #cbd5e0;
|
|
332
|
-
position: sticky;
|
|
333
|
-
top: 0;
|
|
334
|
-
z-index: 10;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/* 第一列(表A)适中宽度 */
|
|
338
|
-
.markdown-content table th:first-child,
|
|
339
|
-
.markdown-content table td:first-child {
|
|
340
|
-
width: 15%;
|
|
341
|
-
min-width: 140px;
|
|
342
|
-
font-weight: 500;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/* 第二列(关系类型)窄一些 */
|
|
346
|
-
.markdown-content table th:nth-child(2),
|
|
347
|
-
.markdown-content table td:nth-child(2) {
|
|
348
|
-
width: 8%;
|
|
349
|
-
min-width: 70px;
|
|
350
|
-
text-align: center;
|
|
351
|
-
font-weight: 500;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/* 第三列(表B)适中宽度 */
|
|
355
|
-
.markdown-content table th:nth-child(3),
|
|
356
|
-
.markdown-content table td:nth-child(3) {
|
|
357
|
-
width: 15%;
|
|
358
|
-
min-width: 140px;
|
|
359
|
-
font-weight: 500;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/* 第四列(关联字段)较宽 */
|
|
363
|
-
.markdown-content table th:nth-child(4),
|
|
364
|
-
.markdown-content table td:nth-child(4) {
|
|
365
|
-
width: 22%;
|
|
366
|
-
min-width: 180px;
|
|
367
|
-
font-family: "SF Mono", "Consolas", "Monaco", monospace;
|
|
368
|
-
font-size: 13px;
|
|
369
|
-
color: #4a5568;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/* 最后一列(说明)最宽,自动填充剩余空间 */
|
|
373
|
-
.markdown-content table th:last-child,
|
|
374
|
-
.markdown-content table td:last-child {
|
|
375
|
-
width: 40%;
|
|
376
|
-
min-width: 220px;
|
|
377
|
-
color: #4a5568;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
.markdown-content table tbody tr {
|
|
381
|
-
transition: all 0.15s ease;
|
|
382
|
-
border-bottom: 1px solid #f1f5f9;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
.markdown-content table tbody tr:hover {
|
|
386
|
-
background-color: #f8fafc;
|
|
387
|
-
box-shadow: inset 0 0 0 1px #e2e8f0;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
.markdown-content table tbody tr:last-child {
|
|
391
|
-
border-bottom: none;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/* 字段名样式 */
|
|
395
|
-
.markdown-content table .field-name-cell {
|
|
396
|
-
font-family: "SF Mono", "Consolas", "Monaco", monospace;
|
|
397
|
-
color: #dc2626;
|
|
398
|
-
font-weight: 500;
|
|
399
|
-
font-size: 13px;
|
|
400
|
-
background-color: #fef2f2;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/* 必填标记样式 */
|
|
404
|
-
.markdown-content table .required-yes {
|
|
405
|
-
color: #2d3748;
|
|
330
|
+
background: #f6f8fa;
|
|
406
331
|
font-weight: 600;
|
|
407
|
-
text-align: center;
|
|
408
332
|
}
|
|
409
333
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
height: 8px;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
.markdown-content .table-wrapper::-webkit-scrollbar-track {
|
|
416
|
-
background: #f1f5f9;
|
|
417
|
-
border-radius: 4px;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
.markdown-content .table-wrapper::-webkit-scrollbar-thumb {
|
|
421
|
-
background: #cbd5e0;
|
|
422
|
-
border-radius: 4px;
|
|
423
|
-
transition: background 0.2s;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
.markdown-content .table-wrapper::-webkit-scrollbar-thumb:hover {
|
|
427
|
-
background: #94a3b8;
|
|
334
|
+
.markdown-content table tr:nth-child(2n) {
|
|
335
|
+
background: #f6f8fa;
|
|
428
336
|
}
|
|
429
337
|
|
|
430
338
|
.markdown-content blockquote {
|
|
431
|
-
border-left:
|
|
432
|
-
padding
|
|
433
|
-
margin:
|
|
434
|
-
color: #
|
|
435
|
-
font-style: italic;
|
|
436
|
-
background: #ebf8ff;
|
|
437
|
-
padding: 16px 20px;
|
|
438
|
-
border-radius: 4px;
|
|
339
|
+
border-left: 4px solid #d0d7de;
|
|
340
|
+
padding: 0 16px;
|
|
341
|
+
margin: 0 0 16px;
|
|
342
|
+
color: #656d76;
|
|
439
343
|
}
|
|
440
344
|
|
|
441
345
|
.markdown-content img {
|
|
442
346
|
max-width: 100%;
|
|
443
347
|
height: auto;
|
|
444
|
-
border-radius:
|
|
445
|
-
margin:
|
|
446
|
-
transition: all 0.2s ease;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
.markdown-content img:hover {
|
|
450
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
451
|
-
transform: translateY(-2px);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
/* 可放大图片样式 */
|
|
455
|
-
.zoomable-image {
|
|
456
|
-
cursor: zoom-in !important;
|
|
457
|
-
position: relative;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
.zoomable-image::after {
|
|
461
|
-
content: '🔍';
|
|
462
|
-
position: absolute;
|
|
463
|
-
top: 8px;
|
|
464
|
-
right: 8px;
|
|
465
|
-
background: rgba(0, 0, 0, 0.7);
|
|
466
|
-
color: white;
|
|
467
|
-
padding: 4px 8px;
|
|
468
|
-
border-radius: 4px;
|
|
469
|
-
font-size: 12px;
|
|
470
|
-
opacity: 0;
|
|
471
|
-
transition: opacity 0.2s ease;
|
|
472
|
-
pointer-events: none;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
.zoomable-image:hover::after {
|
|
476
|
-
opacity: 1;
|
|
348
|
+
border-radius: 6px;
|
|
349
|
+
margin: 8px 0;
|
|
477
350
|
}
|
|
478
351
|
|
|
479
352
|
/* Mermaid 图表样式 */
|
|
480
353
|
.markdown-content .mermaid {
|
|
481
|
-
margin:
|
|
354
|
+
margin: 16px 0;
|
|
482
355
|
text-align: center;
|
|
483
356
|
}
|
|
484
357
|
|
|
@@ -488,189 +361,167 @@ body {
|
|
|
488
361
|
}
|
|
489
362
|
|
|
490
363
|
.markdown-content .mermaid-error {
|
|
491
|
-
color: #
|
|
492
|
-
background: #
|
|
364
|
+
color: #cf222e;
|
|
365
|
+
background: #ffebe9;
|
|
493
366
|
padding: 12px;
|
|
494
|
-
border-radius:
|
|
495
|
-
border: 1px solid #
|
|
496
|
-
font-size: 14px;
|
|
367
|
+
border-radius: 6px;
|
|
368
|
+
border: 1px solid #ff8182;
|
|
497
369
|
}
|
|
498
370
|
|
|
499
371
|
/* 滚动条样式 */
|
|
500
372
|
.sidebar::-webkit-scrollbar,
|
|
501
373
|
.content::-webkit-scrollbar {
|
|
502
|
-
width:
|
|
374
|
+
width: 8px;
|
|
503
375
|
}
|
|
504
376
|
|
|
505
377
|
.sidebar::-webkit-scrollbar-thumb,
|
|
506
378
|
.content::-webkit-scrollbar-thumb {
|
|
507
|
-
background: #
|
|
508
|
-
border-radius:
|
|
379
|
+
background: #d0d7de;
|
|
380
|
+
border-radius: 4px;
|
|
509
381
|
}
|
|
510
382
|
|
|
511
383
|
.sidebar::-webkit-scrollbar-thumb:hover,
|
|
512
384
|
.content::-webkit-scrollbar-thumb:hover {
|
|
513
|
-
background: #
|
|
385
|
+
background: #afb8c1;
|
|
514
386
|
}
|
|
515
387
|
|
|
516
388
|
/* 返回顶部按钮 */
|
|
517
389
|
.back-to-top {
|
|
518
390
|
position: fixed;
|
|
519
|
-
right:
|
|
520
|
-
bottom:
|
|
521
|
-
width:
|
|
522
|
-
height:
|
|
391
|
+
right: 24px;
|
|
392
|
+
bottom: 24px;
|
|
393
|
+
width: 48px;
|
|
394
|
+
height: 48px;
|
|
523
395
|
display: flex;
|
|
524
396
|
flex-direction: column;
|
|
525
397
|
align-items: center;
|
|
526
398
|
justify-content: center;
|
|
527
|
-
gap:
|
|
399
|
+
gap: 2px;
|
|
528
400
|
background: #ffffff;
|
|
529
|
-
color: #
|
|
530
|
-
border: 1px solid #
|
|
531
|
-
border-radius:
|
|
401
|
+
color: #656d76;
|
|
402
|
+
border: 1px solid #d0d7de;
|
|
403
|
+
border-radius: 6px;
|
|
532
404
|
cursor: pointer;
|
|
533
|
-
box-shadow: 0
|
|
534
|
-
transition: all 0.
|
|
405
|
+
box-shadow: 0 1px 3px rgba(31, 35, 40, 0.12);
|
|
406
|
+
transition: all 0.1s;
|
|
535
407
|
z-index: 1000;
|
|
536
408
|
}
|
|
537
409
|
|
|
538
410
|
.back-to-top:hover {
|
|
539
|
-
background: #
|
|
540
|
-
color: #
|
|
541
|
-
border-color: #
|
|
542
|
-
box-shadow: 0 6px 16px rgba(49, 130, 206, 0.3);
|
|
543
|
-
transform: translateY(-2px);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
.back-to-top:active {
|
|
547
|
-
transform: translateY(0) scale(0.95);
|
|
411
|
+
background: #e6f7e6;
|
|
412
|
+
color: #3eaf7c;
|
|
413
|
+
border-color: #3eaf7c;
|
|
548
414
|
}
|
|
549
415
|
|
|
550
416
|
.progress-text {
|
|
551
|
-
font-size:
|
|
552
|
-
font-weight:
|
|
553
|
-
line-height: 1;
|
|
554
|
-
color: inherit;
|
|
417
|
+
font-size: 12px;
|
|
418
|
+
font-weight: 500;
|
|
555
419
|
}
|
|
556
420
|
|
|
557
421
|
/* 淡入淡出动画 */
|
|
558
422
|
.fade-enter-active,
|
|
559
423
|
.fade-leave-active {
|
|
560
|
-
transition: opacity 0.
|
|
424
|
+
transition: opacity 0.2s;
|
|
561
425
|
}
|
|
562
426
|
|
|
563
427
|
.fade-enter-from,
|
|
564
428
|
.fade-leave-to {
|
|
565
429
|
opacity: 0;
|
|
566
|
-
transform: translateY(10px);
|
|
567
430
|
}
|
|
568
431
|
|
|
569
432
|
/* 右侧目录样式 */
|
|
570
433
|
.toc-sidebar {
|
|
571
434
|
min-width: 200px;
|
|
572
|
-
max-width:
|
|
435
|
+
max-width: 300px;
|
|
573
436
|
background: #ffffff;
|
|
574
|
-
border-left: 1px solid #
|
|
437
|
+
border-left: 1px solid #d0d7de;
|
|
575
438
|
overflow-y: auto;
|
|
576
439
|
flex-shrink: 0;
|
|
577
|
-
padding:
|
|
578
|
-
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.02);
|
|
440
|
+
padding: 32px 0;
|
|
579
441
|
}
|
|
580
442
|
|
|
581
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 {
|
|
582
452
|
display: flex;
|
|
583
453
|
align-items: center;
|
|
584
454
|
gap: 8px;
|
|
585
|
-
|
|
586
|
-
font-size: 11px;
|
|
455
|
+
font-size: 12px;
|
|
587
456
|
font-weight: 600;
|
|
588
|
-
color: #
|
|
589
|
-
border-bottom: 1px solid #e2e8f0;
|
|
590
|
-
letter-spacing: 0.05em;
|
|
457
|
+
color: #1f2328;
|
|
591
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;
|
|
592
479
|
}
|
|
593
480
|
|
|
594
481
|
.toc-nav {
|
|
595
|
-
padding:
|
|
482
|
+
padding: 12px 0;
|
|
596
483
|
}
|
|
597
484
|
|
|
598
485
|
.toc-item {
|
|
599
486
|
display: block;
|
|
600
|
-
padding:
|
|
601
|
-
color: #
|
|
487
|
+
padding: 4px 16px;
|
|
488
|
+
color: #656d76;
|
|
602
489
|
text-decoration: none;
|
|
603
490
|
font-size: 12px;
|
|
604
|
-
line-height: 1.
|
|
605
|
-
transition: all 0.
|
|
491
|
+
line-height: 1.5;
|
|
492
|
+
transition: all 0.1s;
|
|
606
493
|
border-left: 2px solid transparent;
|
|
607
|
-
overflow: hidden;
|
|
608
|
-
text-overflow: ellipsis;
|
|
609
|
-
white-space: nowrap;
|
|
610
494
|
}
|
|
611
495
|
|
|
612
496
|
.toc-item:hover {
|
|
613
|
-
color: #
|
|
614
|
-
background: #f7fafc;
|
|
497
|
+
color: #3eaf7c;
|
|
615
498
|
}
|
|
616
499
|
|
|
617
500
|
.toc-item.active {
|
|
618
|
-
color: #
|
|
619
|
-
border-left-color: #
|
|
501
|
+
color: #3eaf7c;
|
|
502
|
+
border-left-color: #3eaf7c;
|
|
620
503
|
font-weight: 500;
|
|
621
|
-
background: #ebf8ff;
|
|
622
504
|
}
|
|
623
505
|
|
|
624
|
-
/* 不同层级的缩进 */
|
|
625
506
|
.toc-item.toc-level-1 {
|
|
626
|
-
padding-left:
|
|
627
|
-
font-size: 13px;
|
|
507
|
+
padding-left: 16px;
|
|
628
508
|
font-weight: 500;
|
|
629
|
-
color: #
|
|
630
|
-
margin-top:
|
|
509
|
+
color: #1f2328;
|
|
510
|
+
margin-top: 8px;
|
|
631
511
|
}
|
|
632
512
|
|
|
633
513
|
.toc-item.toc-level-2 {
|
|
634
|
-
padding-left:
|
|
635
|
-
font-size: 12px;
|
|
636
|
-
margin-top: 2px;
|
|
514
|
+
padding-left: 24px;
|
|
637
515
|
}
|
|
638
516
|
|
|
639
517
|
.toc-item.toc-level-3 {
|
|
640
|
-
padding-left:
|
|
518
|
+
padding-left: 32px;
|
|
641
519
|
font-size: 11px;
|
|
642
520
|
}
|
|
643
521
|
|
|
644
522
|
.toc-item.toc-level-4 {
|
|
645
|
-
padding-left:
|
|
646
|
-
font-size: 12px;
|
|
647
|
-
opacity: 0.9;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
.toc-item.toc-level-5 {
|
|
651
|
-
padding-left: 68px;
|
|
652
|
-
font-size: 11px;
|
|
653
|
-
opacity: 0.85;
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
.toc-item.toc-level-6 {
|
|
657
|
-
padding-left: 80px;
|
|
523
|
+
padding-left: 40px;
|
|
658
524
|
font-size: 11px;
|
|
659
|
-
opacity: 0.8;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
/* 目录滚动条样式 */
|
|
663
|
-
.toc-sidebar::-webkit-scrollbar {
|
|
664
|
-
width: 6px;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
.toc-sidebar::-webkit-scrollbar-thumb {
|
|
668
|
-
background: #dcdfe6;
|
|
669
|
-
border-radius: 3px;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
.toc-sidebar::-webkit-scrollbar-thumb:hover {
|
|
673
|
-
background: #c0c4cc;
|
|
674
525
|
}
|
|
675
526
|
|
|
676
527
|
/* 拖拽条样式 */
|
|
@@ -679,40 +530,22 @@ body {
|
|
|
679
530
|
background: transparent;
|
|
680
531
|
cursor: col-resize;
|
|
681
532
|
flex-shrink: 0;
|
|
682
|
-
|
|
683
|
-
transition: background 0.15s;
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
.resizer::before {
|
|
687
|
-
content: '';
|
|
688
|
-
position: absolute;
|
|
689
|
-
top: 0;
|
|
690
|
-
bottom: 0;
|
|
691
|
-
left: -2px;
|
|
692
|
-
right: -2px;
|
|
533
|
+
transition: background 0.1s;
|
|
693
534
|
}
|
|
694
535
|
|
|
695
536
|
.resizer:hover {
|
|
696
|
-
background: #
|
|
537
|
+
background: #d0d7de;
|
|
697
538
|
}
|
|
698
539
|
|
|
699
540
|
.resizer:active {
|
|
700
|
-
background: #
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
.resizer-left {
|
|
704
|
-
margin-left: -1px;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
.resizer-right {
|
|
708
|
-
margin-right: -1px;
|
|
541
|
+
background: #3eaf7c;
|
|
709
542
|
}
|
|
710
543
|
|
|
711
544
|
/* 收起/展开按钮 */
|
|
712
545
|
.collapse-btn,
|
|
713
546
|
.expand-btn {
|
|
714
547
|
position: fixed;
|
|
715
|
-
top:
|
|
548
|
+
top: 16px;
|
|
716
549
|
z-index: 100;
|
|
717
550
|
width: 32px;
|
|
718
551
|
height: 32px;
|
|
@@ -720,30 +553,21 @@ body {
|
|
|
720
553
|
align-items: center;
|
|
721
554
|
justify-content: center;
|
|
722
555
|
background: #ffffff;
|
|
723
|
-
border: 1px solid #
|
|
556
|
+
border: 1px solid #d0d7de;
|
|
724
557
|
border-radius: 6px;
|
|
725
558
|
cursor: pointer;
|
|
726
|
-
color: #
|
|
727
|
-
transition: all 0.
|
|
728
|
-
box-shadow: 0
|
|
559
|
+
color: #656d76;
|
|
560
|
+
transition: all 0.1s;
|
|
561
|
+
box-shadow: 0 1px 3px rgba(31, 35, 40, 0.12);
|
|
729
562
|
}
|
|
730
563
|
|
|
731
564
|
.collapse-btn:hover,
|
|
732
565
|
.expand-btn:hover {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
box-shadow: 0 4px 12px rgba(49, 130, 206, 0.15);
|
|
736
|
-
transform: translateY(-1px);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
.collapse-btn-left {
|
|
740
|
-
left: 16px;
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
.collapse-btn-right {
|
|
744
|
-
right: 16px;
|
|
566
|
+
background: #f6f8fa;
|
|
567
|
+
color: #1f2328;
|
|
745
568
|
}
|
|
746
569
|
|
|
570
|
+
.collapse-btn-left,
|
|
747
571
|
.expand-btn-left {
|
|
748
572
|
left: 16px;
|
|
749
573
|
}
|
|
@@ -768,18 +592,14 @@ body {
|
|
|
768
592
|
width: 240px;
|
|
769
593
|
}
|
|
770
594
|
|
|
771
|
-
.content {
|
|
772
|
-
padding: 20px;
|
|
773
|
-
}
|
|
774
|
-
|
|
775
595
|
.markdown-content {
|
|
776
|
-
padding:
|
|
596
|
+
padding: 16px;
|
|
777
597
|
}
|
|
778
598
|
|
|
779
599
|
.back-to-top {
|
|
780
|
-
right:
|
|
781
|
-
bottom:
|
|
782
|
-
width:
|
|
783
|
-
height:
|
|
600
|
+
right: 16px;
|
|
601
|
+
bottom: 16px;
|
|
602
|
+
width: 40px;
|
|
603
|
+
height: 40px;
|
|
784
604
|
}
|
|
785
|
-
}
|
|
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']
|