feat: 支持读写本地文件
This commit is contained in:
parent
88a9c42aa2
commit
c09c8b5e9c
@ -43,3 +43,9 @@ This template should help get you started developing with Tauri + Vue 3 in Vite.
|
||||
|
||||
1. `npm run tauri add fs`
|
||||
2. `npm run tauri add dialog`
|
||||
|
||||
## 支持读本地目录,读写本地文件
|
||||
|
||||
1. 新建 SelectFolder.vue 用于打开本地目录
|
||||
2. 在 App.vue 使用组件 SelectFolder 和 MarkdownEditor.vue
|
||||
3. 使用 plugin-fs 插件读写本地文件内容
|
||||
|
||||
@ -9,6 +9,22 @@
|
||||
"core:default",
|
||||
"opener:default",
|
||||
"fs:default",
|
||||
"dialog:default"
|
||||
"dialog:default",
|
||||
{
|
||||
"identifier": "fs:scope",
|
||||
"allow": [
|
||||
{
|
||||
"path": "$HOME/**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-app-write",
|
||||
"allow": [
|
||||
{
|
||||
"path": "$HOME/**"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
53
src/App.vue
53
src/App.vue
@ -1,7 +1,12 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
|
||||
import MarkdownEditor from './components/MarkdownEditor.vue'
|
||||
import SelectFolder from './components/SelectFolder.vue'
|
||||
|
||||
const markdownRef = ref(null);
|
||||
const filePath = ref("");
|
||||
const greetMsg = ref("");
|
||||
const name = ref("");
|
||||
|
||||
@ -9,30 +14,46 @@ async function greet() {
|
||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||
greetMsg.value = await invoke("greet", { name: name.value });
|
||||
}
|
||||
|
||||
async function showFileTree(tree) {
|
||||
console.log(tree)
|
||||
}
|
||||
|
||||
async function readFileContent() {
|
||||
try {
|
||||
console.log('文件读取成功:', markdownRef.value.setMarkdownCode(await readTextFile(filePath.value)))
|
||||
} catch (err) {
|
||||
console.error('文件读取失败:', err);
|
||||
}
|
||||
}
|
||||
|
||||
async function writeFileContent() {
|
||||
console.log('文件新的内容:', markdownRef.value.getMarkdownCode())
|
||||
try {
|
||||
console.log('文件更新成功:', await writeTextFile(filePath.value, markdownRef.value.getMarkdownCode()))
|
||||
} catch (err) {
|
||||
console.error('文件更新失败:', err);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="container">
|
||||
<h1>Welcome to Tauri + Vue</h1>
|
||||
<div class="row">
|
||||
<SelectFolder @folder-selected="showFileTree" />
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<a href="https://vitejs.dev" target="_blank">
|
||||
<img src="/vite.svg" class="logo vite" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://tauri.app" target="_blank">
|
||||
<img src="/tauri.svg" class="logo tauri" alt="Tauri logo" />
|
||||
</a>
|
||||
<a href="https://vuejs.org/" target="_blank">
|
||||
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
|
||||
</a>
|
||||
<input id="file-path-input" v-model="filePath" placeholder="Enter a file path..." />
|
||||
<button @click="readFileContent">读取指定文件</button>
|
||||
<button @click="writeFileContent">更新指定文件</button>
|
||||
</div>
|
||||
<p>Click on the Tauri, Vite, and Vue logos to learn more.</p>
|
||||
|
||||
<form class="row" @submit.prevent="greet">
|
||||
<input id="greet-input" v-model="name" placeholder="Enter a name..." />
|
||||
<button type="submit">Greet</button>
|
||||
</form>
|
||||
<p>{{ greetMsg }}</p>
|
||||
<MarkdownEditor ref="markdownRef"
|
||||
width='1000px'
|
||||
height='1000px'
|
||||
markdownCode="# hello tauri"
|
||||
/>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
|
||||
76
src/components/SelectFolder.vue
Normal file
76
src/components/SelectFolder.vue
Normal file
@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<button @click="selectFolder">选择目录</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { join } from '@tauri-apps/api/path';
|
||||
import { open } from '@tauri-apps/plugin-dialog';
|
||||
import { readDir } from '@tauri-apps/plugin-fs';
|
||||
|
||||
// 文件树示例
|
||||
let folderTreeData = {
|
||||
"path": "root-path/root",
|
||||
"name": "root",
|
||||
"nodes": [
|
||||
{
|
||||
"path": "root-path/root/folder1",
|
||||
"name": "folder1",
|
||||
"nodes": [
|
||||
{
|
||||
"path": "root-path/root/folder1/folder1-file2",
|
||||
"name": "folder1-file2.txt.md",
|
||||
"suffix": "md",
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "root-path/root/file3",
|
||||
"name": "file3.txt",
|
||||
"suffix": "txt",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
async function readDirRecursively(parent, path) {
|
||||
// 拼接得到当前文件夹路径
|
||||
const folderPath = await join(parent, path);
|
||||
let folderTreeNode = {
|
||||
"path": folderPath,
|
||||
"name": folderPath.split('/').pop(),
|
||||
"nodes": []
|
||||
}
|
||||
|
||||
// 遍历该文件夹下所有实体
|
||||
const entries = await readDir(folderPath);
|
||||
for (const entry of entries) {
|
||||
const entryPath = await join(folderPath, entry.name);
|
||||
if (entry.isDirectory) {
|
||||
folderTreeNode.nodes.push(await readDirRecursively(folderPath, entry.name))
|
||||
} else {
|
||||
const fileSuffix = entry.name.split('.').pop()
|
||||
folderTreeNode.nodes.push({
|
||||
"path": entryPath,
|
||||
"name": entry.name,
|
||||
"suffix": fileSuffix,
|
||||
})
|
||||
}
|
||||
}
|
||||
return folderTreeNode
|
||||
}
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
async selectFolder() {
|
||||
const filePath = await open(
|
||||
{
|
||||
filters: [{ name: 'All Files', extensions: ['.'] }],
|
||||
directory: true
|
||||
});
|
||||
if (filePath) {
|
||||
folderTreeData = await readDirRecursively(filePath, '')
|
||||
this.$emit('folder-selected', folderTreeData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Loading…
x
Reference in New Issue
Block a user