Skip to content

Commit 5e8c83c

Browse files
committed
feat: 完成目录选择与切换
1 parent d8d5a8e commit 5e8c83c

File tree

11 files changed

+206
-34
lines changed

11 files changed

+206
-34
lines changed

frontend/components.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ declare module 'vue' {
2020
ElInput: typeof import('element-plus/es')['ElInput']
2121
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
2222
ElOption: typeof import('element-plus/es')['ElOption']
23+
ElOptionGroup: typeof import('element-plus/es')['ElOptionGroup']
2324
ElSelect: typeof import('element-plus/es')['ElSelect']
2425
ElSwitch: typeof import('element-plus/es')['ElSwitch']
2526
ElTabPane: typeof import('element-plus/es')['ElTabPane']
@@ -41,6 +42,7 @@ declare global {
4142
const ElInput: typeof import('element-plus/es')['ElInput']
4243
const ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
4344
const ElOption: typeof import('element-plus/es')['ElOption']
45+
const ElOptionGroup: typeof import('element-plus/es')['ElOptionGroup']
4446
const ElSelect: typeof import('element-plus/es')['ElSelect']
4547
const ElSwitch: typeof import('element-plus/es')['ElSwitch']
4648
const ElTabPane: typeof import('element-plus/es')['ElTabPane']

frontend/src/App.vue

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
<template>
2-
<ViewMenu />
3-
<ViewLeft />
4-
<ViewEditor />
2+
<template v-if="user.initialized">
3+
<ViewMenu />
4+
<ViewLeft />
5+
<ViewEditor />
56

6-
<DialogLike />
7-
<DialogOpen />
7+
<DialogLike />
8+
<DialogOpen />
9+
</template>
810
</template>
911

1012
<script setup lang="ts">
13+
import { onMounted } from 'vue'
14+
1115
import ViewMenu from '@/layout/ViewMenu.vue'
1216
import ViewLeft from '@/layout/ViewLeft/LeftBox.vue'
1317
import ViewEditor from '@/layout/ViewEditor.vue'
1418
import DialogLike from '@/layout/DialogLike.vue'
1519
import DialogOpen from '@/layout/DialogOpen.vue'
20+
21+
import { useUserStore } from '@/store/user'
22+
23+
const user = useUserStore()
24+
25+
onMounted(() => {
26+
user.load()
27+
})
1628
</script>
1729

1830
<style lang="scss">

frontend/src/layout/DialogLike.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,14 @@
4747
<div class="item">
4848
<div class="label">默认打开</div>
4949
<div class="value">
50-
<el-switch v-model="cfg.folderDefOpen" inline-prompt />
50+
<el-select
51+
v-model="cfg.folderDefOpen"
52+
size="small"
53+
clearable
54+
placeholder="启动时默认打开某个目录"
55+
>
56+
<el-option v-for="item in user.cfg.dir" :key="item" :label="item" :value="item" />
57+
</el-select>
5158
</div>
5259
</div>
5360

@@ -89,8 +96,10 @@ import { storeToRefs } from 'pinia'
8996
9097
import { THEME_OPTIONS } from '@/utils/option'
9198
99+
import { useUserStore } from '@/store/user'
92100
import { useLikeStore } from '@/store/like'
93101
102+
const user = useUserStore()
94103
const like = useLikeStore()
95104
96105
const { open, cfg } = storeToRefs(like)

frontend/src/layout/DialogOpen.vue

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
<template>
2-
<el-dialog v-model="show" title="打开" width="500" @closed="input = ''">
3-
<el-tabs default-value="file">
2+
<el-dialog
3+
:modelValue="!!show"
4+
@update:modelValue="
5+
(v: boolean) => {
6+
if (v === false) {
7+
show = undefined
8+
}
9+
}
10+
"
11+
title="打开"
12+
width="500"
13+
@closed="input = ''"
14+
>
15+
<el-tabs v-model="show">
416
<el-tab-pane label="文件" name="file">
517
<div class="view-dialog">
6-
<el-input v-model="input" placeholder="请输入文件路径(不存在的文件编辑后可直接新增)">
18+
<el-input
19+
v-model="input"
20+
placeholder="请输入文件路径(不存在的文件编辑后可直接新增)"
21+
class="input"
22+
>
723
<template #append>
824
<el-button @click="editor.add(input)">确认</el-button>
925
</template>
@@ -15,7 +31,7 @@
1531
<el-button size="small" @click="open.clearHistory()">清除全部</el-button>
1632
</div>
1733

18-
<div class="history">
34+
<div class="list">
1935
<div
2036
class="item"
2137
v-for="item in open.history"
@@ -30,6 +46,42 @@
3046
</template>
3147
</div>
3248
</el-tab-pane>
49+
50+
<el-tab-pane label="目录" name="dir">
51+
<div class="view-dialog">
52+
<el-input v-model="input" placeholder="请输入目录路径" class="input">
53+
<template #append>
54+
<el-button @click="addDir(input)">添加目录</el-button>
55+
</template>
56+
</el-input>
57+
58+
<div class="title">
59+
<div class="t">我的目录</div>
60+
61+
<el-select
62+
v-model="cfg.folderDefOpen"
63+
size="small"
64+
clearable
65+
style="width: 200px"
66+
placeholder="选择目录"
67+
>
68+
<el-option-group label="启动时默认打开">
69+
<el-option v-for="item in user.cfg.dir" :key="item" :label="item" :value="item" />
70+
</el-option-group>
71+
</el-select>
72+
</div>
73+
74+
<div class="list">
75+
<div class="item" v-for="item in user.cfg.dir" :key="item" @click="changeDir(item)">
76+
<div class="t">{{ item }}</div>
77+
<div style="flex: 1"></div>
78+
<el-icon v-if="user.cfg.dir.length > 1" class="i" @click.stop="deleteDir(item)">
79+
<Close />
80+
</el-icon>
81+
</div>
82+
</div>
83+
</div>
84+
</el-tab-pane>
3385
</el-tabs>
3486
</el-dialog>
3587
</template>
@@ -39,31 +91,65 @@ import { onMounted } from 'vue'
3991
import { storeToRefs } from 'pinia'
4092
import { Close } from '@element-plus/icons-vue'
4193
94+
import { useUserStore } from '@/store/user'
4295
import { useOpenStore } from '@/store/open'
4396
import { useEditorStore } from '@/store/editor'
97+
import { useLikeStore } from '@/store/like'
4498
99+
const user = useUserStore()
45100
const open = useOpenStore()
101+
const like = useLikeStore()
46102
const editor = useEditorStore()
47103
48104
const { show, input } = storeToRefs(open)
105+
const { cfg } = storeToRefs(like)
49106
50107
onMounted(async () => {
51108
const query = new URLSearchParams(window.location.search).get('path') || ''
52109
if (query) {
53110
editor.add(query)
54111
} else {
55-
show.value = true
112+
show.value = 'file'
56113
}
57114
})
115+
116+
const changeDir = (v: string) => {
117+
like.cfg.folderActive = v
118+
open.show = undefined
119+
}
120+
121+
const addDir = (v: string) => {
122+
const index = user.cfg.dir.findIndex((i) => i === v)
123+
if (index > -1) {
124+
user.cfg.dir.splice(index, 1)
125+
}
126+
127+
user.cfg.dir.unshift(v)
128+
}
129+
130+
const deleteDir = (v: string) => {
131+
const index = user.cfg.dir.findIndex((i) => i === v)
132+
if (index > -1) {
133+
user.cfg.dir.splice(index, 1)
134+
135+
if (cfg.value.folderDefOpen === v) {
136+
cfg.value.folderDefOpen = ''
137+
}
138+
}
139+
}
58140
</script>
59141

60142
<style lang="scss" scoped>
61143
.view-dialog {
62144
display: flex;
63145
flex-direction: column;
64146
147+
> .input {
148+
margin-bottom: 12px;
149+
}
150+
65151
> .title {
66-
margin: 12px 0 4px;
152+
margin-bottom: 4px;
67153
display: flex;
68154
align-items: center;
69155
gap: 12px;
@@ -75,7 +161,7 @@ onMounted(async () => {
75161
}
76162
}
77163
78-
> .history {
164+
> .list {
79165
display: flex;
80166
flex-direction: column;
81167
height: 200px;

frontend/src/layout/ViewEditor.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
<el-tab-pane :name="-1" disabled>
5050
<template #label>
51-
<div class="add" @click="open.show = true">
51+
<div class="add" @click="open.show = 'file'">
5252
<el-icon><Plus /></el-icon>
5353
</div>
5454
</template>
@@ -74,11 +74,12 @@ import { Plus } from '@element-plus/icons-vue'
7474
7575
import MonacoEditor from '@/components/MonacoEditor.vue'
7676
77-
import { useOpenStore } from '@/store/open'
78-
import { useEditorStore } from '@/store/editor'
7977
import { FILE_MAP } from '@/utils/option'
8078
import { getFileName, getFileSuffix, getFullPath } from '@/utils/file'
8179
80+
import { useOpenStore } from '@/store/open'
81+
import { useEditorStore } from '@/store/editor'
82+
8283
const open = useOpenStore()
8384
const editor = useEditorStore()
8485

frontend/src/layout/ViewLeft/ViewFolder.vue

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
<div class="head">
44
<div class="title">目录</div>
55

6-
<!-- <el-icon class="icon"><Setting /></el-icon> -->
6+
<el-icon class="icon" @click="openDir()"><Files /></el-icon>
77
</div>
88

99
<div class="content">
1010
<div class="list">
1111
<el-tree
12-
:props="props"
12+
:key="like.cfg.folderActive"
13+
:props="{ label: 'label', isLeaf: 'leaf' }"
1314
:load="loadNode"
1415
lazy
1516
@node-click="
@@ -38,33 +39,53 @@
3839

3940
<script lang="ts" setup>
4041
import axios from 'axios'
41-
import { Folder, FolderOpened } from '@element-plus/icons-vue'
42+
import { Files, Folder, FolderOpened } from '@element-plus/icons-vue'
4243
4344
import FileView from '@/components/FileView.vue'
4445
46+
import { HOST } from '@/utils/env'
47+
4548
import { useEditorStore } from '@/store/editor'
4649
import { useLikeStore } from '@/store/like'
47-
48-
import { HOST } from '@/utils/env'
50+
import { useOpenStore } from '@/store/open'
4951
5052
import type { LoadFunction } from 'element-plus'
5153
5254
const editor = useEditorStore()
5355
const like = useLikeStore()
56+
const open = useOpenStore()
5457
55-
const props = { label: 'label', children: 'zones', isLeaf: 'leaf' }
58+
const openDir = async () => {
59+
open.show = 'dir'
60+
}
5661
5762
const loadNode: LoadFunction = async (node, resolve) => {
58-
const root = node.data.value || '/Users/flex/Downloads'
63+
const root = node.data.value || like.cfg.folderActive
5964
60-
const { data } = await axios.get<{ data: { dirs: string[]; files: string[] } }>(HOST, {
65+
if (!root) {
66+
return resolve([])
67+
}
68+
69+
const { data: result } = await axios.get<{
70+
code: number
71+
data: { dirs: string[]; files: string[] }
72+
}>(HOST, {
6173
params: { _api: 'dir', path: root },
6274
})
6375
76+
if (result.code !== 200) {
77+
return resolve([])
78+
}
79+
6480
resolve(
6581
[
66-
...data.data.dirs.map((i) => ({ label: i, value: `${root}/${i}`, leaf: false, dir: true })),
67-
...data.data.files.map((i) => ({ label: i, value: `${root}/${i}`, leaf: true, dir: false })),
82+
...result.data.dirs.map((i) => ({ label: i, value: `${root}/${i}`, leaf: false, dir: true })),
83+
...result.data.files.map((i) => ({
84+
label: i,
85+
value: `${root}/${i}`,
86+
leaf: true,
87+
dir: false,
88+
})),
6889
].filter((i) => !like.cfg.folderHidePrefix.some((x) => i.label.indexOf(x) === 0)),
6990
)
7091
}

frontend/src/layout/ViewMenu.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
<el-icon><Timer /></el-icon>
99
</div>
1010

11+
<div style="flex: 1"></div>
12+
1113
<div class="item" :class="{ active: like.open }" @click="like.open = true">
1214
<el-icon><Setting /></el-icon>
1315
</div>

frontend/src/store/editor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const useEditorStore = defineStore('editor', () => {
4141

4242
active.value = path
4343

44-
open.show = false
44+
open.show = undefined
4545

4646
if (history) {
4747
open.addHistory({ path })

frontend/src/store/like.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@ import localStorage from '@/utils/localStorage'
77
interface LikeModel {
88
theme: string
99
leftWidth: number
10-
1110
confirm: boolean
12-
13-
folderDefOpen: boolean
11+
folderActive: string
12+
folderDefOpen: string
1413
folderHidePrefix: string[]
15-
1614
editorOption: {
1715
fontSize: number
1816
wordWrap: 'off' | 'on'
@@ -28,7 +26,8 @@ const getDef = (): LikeModel => ({
2826
confirm: true, // 保存二次确认
2927

3028
// 目录
31-
folderDefOpen: false, // 默认开启目录
29+
folderActive: '', // 当前打开的目录
30+
folderDefOpen: '', // 默认开启目录
3231
folderHidePrefix: ['.'], // 隐藏的文件前缀
3332

3433
// 编辑器

0 commit comments

Comments
 (0)