2025-04-08 02:04:18 +08:00

160 lines
5.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import { ref, watch, useTemplateRef, onMounted, onUnmounted } from "vue";
import { invoke } from "@tauri-apps/api/core";
import { readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
import { Message } from 'view-ui-plus'
import MarkdownEditor from './components/MarkdownEditor.vue'
import SelectFolder from './components/SelectFolder.vue'
import FolderTree from './components/FolderTree.vue'
// 原始示例数据,仅供参考
const greetMsg = ref("");
const name = ref("");
async function greet() {
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
greetMsg.value = await invoke("greet", { name: name.value });
}
const markdownRef = ref(null);
// 矫正 markdown 编辑器的高度
function reloadEditorHeight() {
markdownRef.value.resetHeight(window.innerHeight)
}
// 矫正 markdown 编辑器的宽度
function reloadEditorWidth() {
// 可以使用 splitRight.value.offsetWidth 也可以使用 100% 来调整
const width = splitRight.value.offsetWidth
markdownRef.value.resetWidth("100%")
}
// 监听页面宽度和高度,调整 markdown 编辑器的高宽度
const handleWindowResize = () => {
reloadEditorHeight()
reloadEditorWidth()
}
onMounted(() => window.addEventListener('resize', handleWindowResize))
onUnmounted(() => window.removeEventListener('resize', handleWindowResize))
// 动态控制页面左右布局
const split = ref(0.2)
const hiddenSplitRight = ref("")
const splitRight = useTemplateRef('splitRight')
watch(split, (newSplit, oldSplit) => {
// 当 split 小于某个值时,隐藏左边布局
if (newSplit < 0.05) {
split.value = 0.01
if (hiddenSplitRight.value == "") {
hiddenSplitRight.value = "hidden"
}
} else {
if (hiddenSplitRight.value == "hidden") {
hiddenSplitRight.value = ""
}
}
// 动态调整 MarkdownEditor 的宽度。如果不执行 reset 的话CodeMirror 内部编辑器不会自适应宽度
reloadEditorWidth()
})
// 如果之前已经选过目录,那么直接加载该目录
const rootPathOfFolderTree = ref(localStorage.getItem('rootPathOfFolderTree') || "")
function changeRootPath(newRootPath) {
localStorage.setItem('rootPathOfFolderTree', newRootPath)
rootPathOfFolderTree.value = newRootPath
}
// <SelectFolder> 选择目录后赋值给 folderTreeData然后再传递给 <FolderTree>
const folderTreeData = ref(null)
function showFileTree(treeData) {
folderTreeData.value = treeData
}
// <FolderTree> 完成文件树渲染后,点击文件得到 currentFilePath
// 读取 currentFilePath 的文件内容,填充到 MarkdownEditor 之中
const currentFilePath = ref("");
const loadingCurrentFile = ref(true);
async function loadFileContent(fileNodeData) {
console.log(fileNodeData)
const filePath = fileNodeData.path
currentFilePath.value = filePath
loadingCurrentFile.value = true
await readFileContent(filePath)
}
async function readFileContent(filePath) {
try {
markdownRef.value.setMarkdownCode(await readTextFile(filePath))
Message.success('已读取文件内容,并加载到编辑器中:' + filePath);
} catch (err) {
Message.error('文件读取失败:' + err);
}
}
async function writeFileContent() {
try {
// 如果触发当前事件,是因为刚点击并加载了某个文件内容,则不执行写文件操作
if (!loadingCurrentFile.value) {
await writeTextFile(currentFilePath.value, markdownRef.value.getMarkdownCode())
}
loadingCurrentFile.value = false
} catch (err) {
Message.error('文件更新失败:' + err);
}
}
</script>
<template>
<div>
<Split v-model="split">
<template #left>
<div class="split-left">
<SelectFolder :class="hiddenSplitRight" :rootPath="rootPathOfFolderTree" @update:rootPath="changeRootPath"
@folder-selected="showFileTree" />
<FolderTree :class="hiddenSplitRight" :treeData="folderTreeData" :expandLevel="1"
:specifyFileSuffix="['md']" @file-selected="loadFileContent" />
</div>
</template>
<template #trigger>
<div class="split-trigger"></div>
</template>
<template #right>
<div ref="splitRight" class="split-right">
<MarkdownEditor ref="markdownRef" width="100%" height="100%" markdownCode="# hello tauri"
:onload="reloadEditorHeight" :onfullscreenExit="handleWindowResize" @update:markdownCode="writeFileContent" />
</div>
</template>
</Split>
</div>
</template>
<style scoped>
body {
overflow: hidden;
/* 禁用所有方向滚动 */
}
.split-left {
height: 100vh;
border-right: 1px solid #dcdee2;
overflow-x: hidden;
overflow-y: auto;
scrollbar-width: none;
}
.split-trigger {
width: 5px;
height: 100vh;
background-color: gray;
}
.split-trigger:hover {
cursor: ew-resize;
}
.split-right {
margin-left: 5px;
}
.hidden {
display: none;
}
</style>
<style></style>