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`
|
1. `npm run tauri add fs`
|
||||||
2. `npm run tauri add dialog`
|
2. `npm run tauri add dialog`
|
||||||
|
|
||||||
|
## 支持读本地目录,读写本地文件
|
||||||
|
|
||||||
|
1. 新建 SelectFolder.vue 用于打开本地目录
|
||||||
|
2. 在 App.vue 使用组件 SelectFolder 和 MarkdownEditor.vue
|
||||||
|
3. 使用 plugin-fs 插件读写本地文件内容
|
||||||
|
|||||||
@ -9,6 +9,22 @@
|
|||||||
"core:default",
|
"core:default",
|
||||||
"opener:default",
|
"opener:default",
|
||||||
"fs: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>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
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 greetMsg = ref("");
|
||||||
const name = ref("");
|
const name = ref("");
|
||||||
|
|
||||||
@ -9,30 +14,46 @@ async function greet() {
|
|||||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||||
greetMsg.value = await invoke("greet", { name: name.value });
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<main class="container">
|
<main class="container">
|
||||||
<h1>Welcome to Tauri + Vue</h1>
|
<div class="row">
|
||||||
|
<SelectFolder @folder-selected="showFileTree" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<a href="https://vitejs.dev" target="_blank">
|
<input id="file-path-input" v-model="filePath" placeholder="Enter a file path..." />
|
||||||
<img src="/vite.svg" class="logo vite" alt="Vite logo" />
|
<button @click="readFileContent">读取指定文件</button>
|
||||||
</a>
|
<button @click="writeFileContent">更新指定文件</button>
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
<p>Click on the Tauri, Vite, and Vue logos to learn more.</p>
|
|
||||||
|
|
||||||
<form class="row" @submit.prevent="greet">
|
<MarkdownEditor ref="markdownRef"
|
||||||
<input id="greet-input" v-model="name" placeholder="Enter a name..." />
|
width='1000px'
|
||||||
<button type="submit">Greet</button>
|
height='1000px'
|
||||||
</form>
|
markdownCode="# hello tauri"
|
||||||
<p>{{ greetMsg }}</p>
|
/>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</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