654 lines
15 KiB
CSS
654 lines
15 KiB
CSS
@import '@/components/LargeMarkdownViewer/LargeMarkdownViewer.css';
|
||
|
||
.document-editor-page {
|
||
height: calc(100vh - 64px);
|
||
/* width: calc(100% + 32px); */
|
||
display: flex;
|
||
margin: -16px;
|
||
padding: 8px;
|
||
box-sizing: border-box;
|
||
background: var(--bg-color);
|
||
}
|
||
|
||
.document-editor-container {
|
||
height: 100%;
|
||
width: 100%;
|
||
display: flex;
|
||
flex: 1;
|
||
}
|
||
|
||
.document-sider {
|
||
border-right: 1px solid var(--border-color);
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: hidden;
|
||
flex-shrink: 0;
|
||
background: var(--sider-bg);
|
||
}
|
||
|
||
/* 修复 Sider 内部 flex 布局 */
|
||
.document-sider .ant-layout-sider-children {
|
||
display: flex;
|
||
flex-direction: column;
|
||
height: 100%;
|
||
}
|
||
|
||
.sider-header {
|
||
padding: 12px 10px 12px;
|
||
border-bottom: 1px solid var(--border-color);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
background: var(--header-bg);
|
||
}
|
||
|
||
.sider-header h2 {
|
||
margin: 0;
|
||
font-size: 20px;
|
||
font-weight: 700;
|
||
letter-spacing: 0;
|
||
color: var(--text-color);
|
||
line-height: 1.1;
|
||
}
|
||
|
||
.sider-title-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 14px;
|
||
min-width: 0;
|
||
}
|
||
|
||
.sider-title-row h2 {
|
||
flex: 1;
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.project-back-button {
|
||
width: 28px;
|
||
height: 28px;
|
||
border: none;
|
||
border-radius: 999px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: transparent;
|
||
color: var(--text-color-secondary);
|
||
font-size: 16px;
|
||
cursor: pointer;
|
||
flex-shrink: 0;
|
||
transition: background 0.2s ease, color 0.2s ease, transform 0.2s ease;
|
||
}
|
||
|
||
.project-back-button:hover {
|
||
background: var(--item-hover-bg);
|
||
color: var(--text-color);
|
||
transform: translateX(-1px);
|
||
}
|
||
|
||
.project-back-button:focus-visible {
|
||
outline: 2px solid rgba(22, 119, 255, 0.35);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
.sider-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.mode-actions-row {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 12px;
|
||
}
|
||
|
||
.mode-actions-group {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.sider-actions .mode-actions-group .ant-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 32px;
|
||
height: 32px;
|
||
color: var(--text-color-secondary);
|
||
}
|
||
|
||
.sider-actions .mode-actions-group .ant-btn:hover {
|
||
background: var(--item-hover-bg);
|
||
border-color: var(--border-color);
|
||
color: var(--link-color);
|
||
}
|
||
|
||
.document-content {
|
||
height: 100%;
|
||
width: 100%;
|
||
background: var(--bg-color);
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
/* 强制覆盖 Ant Design Content 的默认样式 */
|
||
.document-editor-container .ant-layout-content {
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
flex: 1 !important;
|
||
min-width: 0 !important;
|
||
width: 100% !important;
|
||
}
|
||
|
||
.content-header {
|
||
padding: 16px 24px;
|
||
min-height: 57px;
|
||
border-bottom: 1px solid var(--border-color);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 16px;
|
||
background: var(--header-bg);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.editor-container {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-height: 0;
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
width: 100%;
|
||
}
|
||
|
||
.bytemd-wrapper {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
/* Changed to column to force child stretch width */
|
||
min-height: 0;
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
width: 100%;
|
||
height: 100%;
|
||
padding: 5px 10px;
|
||
}
|
||
|
||
.bytemd-wrapper.large-file-editor {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* Fix for bytemd-react wrapper div(仅普通编辑器,超大着色编辑器不受此约束) */
|
||
.bytemd-wrapper:not(.large-file-editor)>div {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
width: 100% !important;
|
||
height: 100% !important;
|
||
min-width: 0;
|
||
}
|
||
|
||
.empty-editor {
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--text-color-secondary);
|
||
}
|
||
|
||
/* 文件夹视图滚动容器(复用浏览模式 docs-folder-* 布局,仅新增滚动) */
|
||
.editor-folder-scroll {
|
||
flex: 1;
|
||
min-height: 0;
|
||
min-width: 0;
|
||
overflow-y: auto;
|
||
width: 100%;
|
||
}
|
||
|
||
/* PDF 只读预览(编辑模式下内置,与浏览模式一致) */
|
||
.pdf-editor-container {
|
||
flex: 1;
|
||
min-height: 0;
|
||
min-width: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: hidden;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: var(--bg-color);
|
||
}
|
||
|
||
.pdf-header-toolbar {
|
||
min-width: 0;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;
|
||
}
|
||
|
||
.pdf-header-toolbar .pdf-toolbar {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* ByteMD 编辑器样式覆盖 */
|
||
.bytemd {
|
||
width: 100% !important;
|
||
height: 100% !important;
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
border: 1px solid var(--border-color);
|
||
border-radius: 2px;
|
||
overflow: hidden;
|
||
max-width: none !important;
|
||
/* Ensure no max-width constraint */
|
||
box-sizing: border-box;
|
||
background-color: var(--bg-color);
|
||
color: var(--text-color);
|
||
}
|
||
|
||
/* 工具栏样式 */
|
||
.bytemd-toolbar {
|
||
flex-shrink: 0;
|
||
border-bottom: 1px solid var(--border-color);
|
||
background-color: var(--toolbar-bg);
|
||
box-sizing: border-box;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.bytemd-toolbar-icon {
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.bytemd-toolbar-icon:hover {
|
||
background-color: var(--item-hover-bg);
|
||
}
|
||
|
||
/* ByteMD 内置的右侧按钮:1=目录 2=帮助 3=仅编辑 4=仅预览 5=全屏 6=源代码。
|
||
1/2 依赖预览区渲染,3/4 与页面自身的「编辑 / 分栏 / 预览」分段控件重复,统一隐藏;
|
||
5 由页面自绘、并入同一分段控件的「全屏」取代(DOM 仍保留,靠它驱动 ByteMD 的全屏状态);
|
||
6「源代码」是 ByteMD 指向项目主页的外链,不属于文档编辑操作,编辑模式下统一去掉。
|
||
隐藏后右侧只剩页面 Portal 注入的统一视图控件。
|
||
注意:页面用 Portal 把分段控件插到 .bytemd-toolbar-right 的最后一个子节点,
|
||
上面的序号才不会被错位,改动插入位置时记得同步这里的 nth-child。 */
|
||
.bytemd-toolbar-right .bytemd-toolbar-icon:nth-child(-n+6) {
|
||
display: none;
|
||
}
|
||
|
||
/* 工具栏右侧改成 flex,让「编辑 / 分栏 / 预览」和内置图标同一行居中对齐 */
|
||
.bytemd-toolbar-right {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
/* 视图模式切换(Portal 注入):编辑 / 分栏 / 预览 / 全屏 合成同一分段控件,
|
||
ByteMD 自带图标已全部隐藏,它成为工具栏右侧唯一的控件 */
|
||
.bytemd-toolbar-right .view-mode-switch {
|
||
order: -1;
|
||
line-height: 1;
|
||
}
|
||
|
||
/* 让单个选项与右侧 24px 图标按钮同高,整条控件不会把工具栏撑高 */
|
||
.bytemd-toolbar-right .view-mode-switch .ant-segmented-item-label {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 20px;
|
||
padding-inline: 7px;
|
||
}
|
||
|
||
.bytemd-toolbar-right .view-mode-switch .view-mode-option {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
font-size: 14px;
|
||
}
|
||
|
||
/* 全屏是开关动作而非视图选项:用主色区分「已进入全屏」,图标同时切换为退出样式 */
|
||
.bytemd-toolbar-right .view-mode-switch .view-mode-option.is-active {
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
/* 预览模式是只读视图:隐藏会改动源码的 Markdown 工具栏,以及失效的同步滚动开关 */
|
||
.bytemd-wrapper[data-view-mode="preview"] .bytemd-toolbar-left {
|
||
display: none;
|
||
}
|
||
|
||
.bytemd-wrapper:not([data-view-mode="split"]) .bytemd-status-right label {
|
||
display: none;
|
||
}
|
||
|
||
/* 视图模式:编辑器始终以 split 渲染(保证 Markdown 工具栏可用),
|
||
通过显隐控制编辑区/预览区,覆盖 ByteMD 写死的 width:50% 内联样式。 */
|
||
.bytemd-wrapper[data-view-mode="edit"] .bytemd-editor,
|
||
.bytemd-wrapper[data-view-mode="preview"] .bytemd-preview {
|
||
width: 100% !important;
|
||
}
|
||
|
||
.bytemd-wrapper[data-view-mode="edit"] .bytemd-preview,
|
||
.bytemd-wrapper[data-view-mode="preview"] .bytemd-editor {
|
||
display: none !important;
|
||
}
|
||
|
||
/* 头部右侧操作区(视图模式切换已移入编辑器工具栏) */
|
||
.content-header-actions {
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
/* 保存按钮:自动保存开关融合在按钮内部,整体呈现为一个主色按钮
|
||
左半边「保存」执行保存,右半边「自动保存」开关切换自动保存 */
|
||
.save-control {
|
||
display: inline-flex;
|
||
align-items: stretch;
|
||
height: 32px;
|
||
border-radius: var(--radius-sm);
|
||
background: var(--color-primary);
|
||
color: var(--text-color-inverse);
|
||
overflow: hidden;
|
||
transition: background var(--transition-fast);
|
||
}
|
||
|
||
.save-control:hover {
|
||
background: var(--color-primary-hover);
|
||
}
|
||
|
||
.save-control-main {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 0 12px;
|
||
border: 0;
|
||
background: transparent;
|
||
color: inherit;
|
||
font-size: 14px;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
transition: background var(--transition-fast);
|
||
}
|
||
|
||
.save-control-main:hover:not(:disabled) {
|
||
background: rgba(255, 255, 255, 0.14);
|
||
}
|
||
|
||
.save-control-main:disabled {
|
||
cursor: not-allowed;
|
||
opacity: 0.6;
|
||
}
|
||
|
||
.save-control-sep {
|
||
align-self: center;
|
||
width: 1px;
|
||
height: 16px;
|
||
background: rgba(255, 255, 255, 0.35);
|
||
}
|
||
|
||
.save-control-auto {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
padding: 0 10px;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
transition: background var(--transition-fast);
|
||
}
|
||
|
||
.save-control-auto:hover {
|
||
background: rgba(255, 255, 255, 0.14);
|
||
}
|
||
|
||
/* 开关本身不单独响应点击,由外层整块统一处理,避免重复触发 */
|
||
.save-control-auto .ant-switch {
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* 主色按钮上的开关重新配色:开关内直接显示「自动 / 手动」,开 / 关都清晰可辨 */
|
||
.save-control-auto .ant-switch {
|
||
background: rgba(0, 0, 0, 0.28);
|
||
/* antd 默认宽度放不下两个汉字,会折行/裁切,这里给足文本空间 */
|
||
min-width: 58px;
|
||
}
|
||
|
||
.save-control-auto .ant-switch .ant-switch-handle::before {
|
||
background: #fff;
|
||
}
|
||
|
||
.save-control-auto .ant-switch.ant-switch-checked {
|
||
background: #fff;
|
||
}
|
||
|
||
/* antd 把颜色写在子节点上,必须直接覆盖 checked / unchecked 文本,否则白字压白底看不见 */
|
||
.save-control-auto .ant-switch .ant-switch-inner-checked,
|
||
.save-control-auto .ant-switch .ant-switch-inner-unchecked {
|
||
color: #fff;
|
||
font-size: 12px;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.save-control-auto .ant-switch.ant-switch-checked .ant-switch-inner-checked {
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
.save-control-auto .ant-switch.ant-switch-checked .ant-switch-handle::before {
|
||
background: var(--color-primary);
|
||
}
|
||
|
||
/* 编辑器工具栏里的视图模式图标(文案放在 Tooltip 中) */
|
||
.view-mode-option {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
line-height: 1;
|
||
}
|
||
|
||
.editor-floating-toc {
|
||
z-index: 20;
|
||
}
|
||
|
||
/* ByteMD 全屏:position: fixed 但没写 z-index,会被 ModeSwitch(z-index:1) 等浮层压住,
|
||
导致左侧项目树的操作按钮浮现在全屏编辑器上;这里显式抬到悬浮层。 */
|
||
.bytemd-fullscreen.bytemd {
|
||
z-index: var(--z-float);
|
||
}
|
||
|
||
/* 全屏时文档索引浮标要跟着抬一层,保证仍在全屏编辑器之上可点 */
|
||
.bytemd-wrapper:has(.bytemd-fullscreen) .editor-floating-toc {
|
||
z-index: calc(var(--z-float) + 1);
|
||
}
|
||
|
||
/* 编辑和预览区域容器 */
|
||
.bytemd-body {
|
||
flex: 1 !important;
|
||
display: flex !important;
|
||
overflow: hidden;
|
||
min-height: 0;
|
||
width: 100% !important;
|
||
box-sizing: border-box;
|
||
/* Added for consistent box model */
|
||
min-width: 0;
|
||
/* Prevent flex item from overflowing */
|
||
background-color: var(--bg-color);
|
||
}
|
||
|
||
/* 编辑区域 - 默认分栏,保留 Bytemd 内联样式对仅编辑/仅预览的控制 */
|
||
.bytemd-editor {
|
||
overflow: hidden;
|
||
min-height: 0;
|
||
box-sizing: border-box;
|
||
/* Added for consistent box model */
|
||
min-width: 0;
|
||
/* Prevent flex item from overflowing */
|
||
background-color: var(--bg-color);
|
||
}
|
||
|
||
.bytemd-wrapper[data-view-mode="split"] .bytemd-editor {
|
||
border-right: 1px solid var(--border-color);
|
||
}
|
||
|
||
/* 预览区域 - 默认分栏,保留 Bytemd 内联样式对仅编辑/仅预览的控制 */
|
||
.bytemd-preview {
|
||
overflow-y: auto !important;
|
||
overflow-x: hidden !important;
|
||
padding: 16px;
|
||
font-size: 14px;
|
||
line-height: 1.8;
|
||
box-sizing: border-box;
|
||
/* Added for consistent box model */
|
||
min-width: 0;
|
||
/* Prevent flex item from overflowing */
|
||
background-color: var(--bg-color);
|
||
color: var(--text-color);
|
||
}
|
||
|
||
/* CodeMirror 容器 */
|
||
.bytemd-editor .CodeMirror {
|
||
flex: 1;
|
||
min-height: 0;
|
||
font-size: 14px;
|
||
line-height: 1.8;
|
||
width: 100%;
|
||
height: 100%;
|
||
background-color: var(--bg-color);
|
||
color: var(--text-color);
|
||
}
|
||
|
||
/* CodeMirror 滚动容器 */
|
||
.bytemd-editor .CodeMirror-scroll {
|
||
overflow-y: scroll !important;
|
||
overflow-x: auto !important;
|
||
min-height: 100% !important;
|
||
height: 100% !important;
|
||
}
|
||
|
||
/* 预览区域的markdown样式 */
|
||
.bytemd-preview h1,
|
||
.bytemd-preview h2,
|
||
.bytemd-preview h3,
|
||
.bytemd-preview h4,
|
||
.bytemd-preview h5,
|
||
.bytemd-preview h6 {
|
||
margin-top: 24px;
|
||
margin-bottom: 16px;
|
||
font-weight: 600;
|
||
line-height: 1.25;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.bytemd-preview h1 {
|
||
font-size: 2em;
|
||
border-bottom: 1px solid var(--border-color);
|
||
padding-bottom: 0.3em;
|
||
}
|
||
|
||
.bytemd-preview h2 {
|
||
font-size: 1.5em;
|
||
border-bottom: 1px solid var(--border-color);
|
||
padding-bottom: 0.3em;
|
||
}
|
||
|
||
.bytemd-preview p {
|
||
margin-bottom: 16px;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.bytemd-preview code {
|
||
padding: 0.2em 0.4em;
|
||
margin: 0;
|
||
font-size: 85%;
|
||
background-color: var(--code-bg);
|
||
border-radius: 3px;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.bytemd-preview pre {
|
||
padding: 16px;
|
||
overflow: auto;
|
||
font-size: 85%;
|
||
line-height: 1.45;
|
||
background-color: var(--code-bg);
|
||
border-radius: 3px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.bytemd-preview pre code {
|
||
display: inline;
|
||
padding: 0;
|
||
margin: 0;
|
||
overflow: visible;
|
||
line-height: inherit;
|
||
background-color: transparent;
|
||
border: 0;
|
||
color: inherit;
|
||
}
|
||
|
||
.bytemd-preview img {
|
||
max-width: 100%;
|
||
box-sizing: content-box;
|
||
}
|
||
|
||
.bytemd-preview table {
|
||
border-collapse: collapse;
|
||
border-spacing: 0;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.bytemd-preview table th,
|
||
.bytemd-preview table td {
|
||
padding: 6px 13px;
|
||
border: 1px solid var(--table-border-color);
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.bytemd-preview table th {
|
||
font-weight: 600;
|
||
background-color: var(--table-header-bg);
|
||
}
|
||
|
||
.bytemd-preview blockquote {
|
||
margin: 0 0 16px;
|
||
padding: 0 1em;
|
||
color: var(--blockquote-text-color);
|
||
border-left: 0.25em solid var(--blockquote-border-color);
|
||
}
|
||
|
||
.bytemd-preview ul,
|
||
.bytemd-preview ol {
|
||
padding-left: 2em;
|
||
margin-bottom: 16px;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.bytemd-preview li {
|
||
margin-bottom: 0.25em;
|
||
}
|
||
|
||
.content-header .preview-header-title {
|
||
flex: 1;
|
||
min-width: 0;
|
||
max-width: none;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.document-editor-page {
|
||
padding: 8px;
|
||
}
|
||
}
|
||
|
||
/* 未保存改动标记:与保存按钮同处内容区右上角,弱化但可辨识 */
|
||
.content-header-actions .unsaved-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
height: 22px;
|
||
padding: 0 var(--space-xs);
|
||
font-size: 12px;
|
||
line-height: 1;
|
||
color: var(--color-warning);
|
||
background: var(--color-warning-bg);
|
||
border: 1px solid var(--color-warning);
|
||
border-radius: var(--radius-pill);
|
||
}
|