Skip to content

Commit 683aeb9

Browse files
committed
feat: 开启文件支持历史记录
1 parent af85629 commit 683aeb9

File tree

6 files changed

+145
-27
lines changed

6 files changed

+145
-27
lines changed

frontend/components.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@ declare module 'vue' {
1515
ElButton: typeof import('element-plus/es')['ElButton']
1616
ElDialog: typeof import('element-plus/es')['ElDialog']
1717
ElIcon: typeof import('element-plus/es')['ElIcon']
18+
ElInput: typeof import('element-plus/es')['ElInput']
1819
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
1920
ElOption: typeof import('element-plus/es')['ElOption']
2021
ElSelect: typeof import('element-plus/es')['ElSelect']
2122
ElSwitch: typeof import('element-plus/es')['ElSwitch']
2223
ElTabPane: typeof import('element-plus/es')['ElTabPane']
2324
ElTabs: typeof import('element-plus/es')['ElTabs']
2425
ElTooltip: typeof import('element-plus/es')['ElTooltip']
26+
LikeDialog: typeof import('./src/components/LikeDialog.vue')['default']
2527
MonacoEditor: typeof import('./src/components/MonacoEditor.vue')['default']
28+
PathDialog: typeof import('./src/components/PathDialog.vue')['default']
2629
}
2730
}
2831

@@ -31,12 +34,15 @@ declare global {
3134
const ElButton: typeof import('element-plus/es')['ElButton']
3235
const ElDialog: typeof import('element-plus/es')['ElDialog']
3336
const ElIcon: typeof import('element-plus/es')['ElIcon']
37+
const ElInput: typeof import('element-plus/es')['ElInput']
3438
const ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
3539
const ElOption: typeof import('element-plus/es')['ElOption']
3640
const ElSelect: typeof import('element-plus/es')['ElSelect']
3741
const ElSwitch: typeof import('element-plus/es')['ElSwitch']
3842
const ElTabPane: typeof import('element-plus/es')['ElTabPane']
3943
const ElTabs: typeof import('element-plus/es')['ElTabs']
4044
const ElTooltip: typeof import('element-plus/es')['ElTooltip']
45+
const LikeDialog: typeof import('./src/components/LikeDialog.vue')['default']
4146
const MonacoEditor: typeof import('./src/components/MonacoEditor.vue')['default']
47+
const PathDialog: typeof import('./src/components/PathDialog.vue')['default']
4248
}

frontend/src/App.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
<el-tab-pane :name="-1" disabled>
2222
<template #label>
23-
<div class="add" @click="add()">
23+
<div class="add" @click="() => (pathOpen = true)">
2424
<el-icon><Plus /></el-icon>
2525
</div>
2626
</template>
@@ -37,6 +37,8 @@
3737
</el-button>
3838

3939
<LikeDialog v-model:open="likeOpen" v-model:like="like" @reset="resetLike()" />
40+
41+
<PathDialog v-model:open="pathOpen" :history="history.value" @open="add" />
4042
</template>
4143

4244
<script setup lang="ts">
@@ -45,12 +47,13 @@ import { Plus } from '@element-plus/icons-vue'
4547
4648
import MonacoEditor from '@/components/MonacoEditor.vue'
4749
import LikeDialog from '@/components/LikeDialog.vue'
50+
import PathDialog from '@/components/PathDialog.vue'
4851
4952
import useLike from '@/hooks/useLike'
5053
import usePath from '@/hooks/usePath'
5154
5255
const { open: likeOpen, like, resetLike } = useLike()
53-
const { view, active, add, remove } = usePath()
56+
const { open: pathOpen, view, active, add, remove, history } = usePath()
5457
5558
const editorRef = ref<any[]>([])
5659
</script>

frontend/src/components/LikeDialog.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
<div style="flex: 1"></div>
3838

39-
<div style="font-size: 12px; color: #999">修改实时生效,且进行缓存</div>
39+
<div style="font-size: 12px; color: var(--el-text-color-placeholder)">修改实时生效,且进行缓存</div>
4040
</div>
4141
</template>
4242
</el-dialog>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<template>
2+
<el-dialog v-model="open" title="打开" width="500">
3+
<div class="path-dialog">
4+
<div class="open">
5+
<div class="title">文件</div>
6+
7+
<el-input v-model="input" placeholder="请输入文件路径(不存在的文件编辑后可直接新增)">
8+
<template #append>
9+
<el-button @click="openPath">确认</el-button>
10+
</template>
11+
</el-input>
12+
</div>
13+
14+
<div class="history">
15+
<div class="title">历史记录</div>
16+
<div class="list" v-if="history.length">
17+
<div class="item" v-for="item in history" :key="item.path">
18+
<div class="i" @click="emit('open', item.path)">{{ item.path }}</div>
19+
</div>
20+
</div>
21+
</div>
22+
</div>
23+
</el-dialog>
24+
</template>
25+
26+
<script lang="ts" setup>
27+
import { ref } from 'vue'
28+
29+
defineProps<{ history: { path: string }[] }>()
30+
31+
const emit = defineEmits<{ (e: 'open', v: string): void }>()
32+
33+
const open = defineModel('open')
34+
35+
const input = ref('')
36+
37+
const openPath = () => {
38+
emit('open', input.value)
39+
input.value = ''
40+
}
41+
</script>
42+
43+
<style lang="scss" scoped>
44+
.path-dialog {
45+
display: flex;
46+
flex-direction: column;
47+
gap: 24px;
48+
49+
> div {
50+
> .title {
51+
font-size: 12px;
52+
margin-bottom: 12px;
53+
color: var(--el-text-color-placeholder);
54+
}
55+
}
56+
57+
> .history {
58+
> .list {
59+
display: flex;
60+
flex-direction: column;
61+
gap: 8px;
62+
height: 200px;
63+
overflow: auto;
64+
65+
> .item {
66+
display: flex;
67+
align-items: center;
68+
69+
> .i {
70+
cursor: pointer;
71+
72+
&:hover {
73+
text-decoration: underline;
74+
}
75+
}
76+
}
77+
}
78+
}
79+
}
80+
</style>

frontend/src/hooks/useHistory.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { reactive, watch } from 'vue'
2+
3+
import localStorage from '@/utils/localStorage'
4+
5+
export default function usePath<T>(opt: { key: string; id: keyof T }) {
6+
const value = reactive<T[]>(localStorage.get<T[]>(opt.key) || [])
7+
8+
const add = (val: T) => {
9+
if (!val) {
10+
return
11+
}
12+
13+
remove(val)
14+
;(value as T[]).unshift(val)
15+
}
16+
17+
const remove = (val: T) => {
18+
if (!val) {
19+
return
20+
}
21+
22+
const index = value.findIndex((i) => (i as T)[opt.id] === val[opt.id])
23+
24+
if (index > -1) {
25+
value.splice(index, 1)
26+
}
27+
}
28+
29+
watch(
30+
() => value,
31+
(v) => {
32+
localStorage.set(opt.key, v)
33+
},
34+
{ deep: true },
35+
)
36+
37+
return { value, add, remove }
38+
}

frontend/src/hooks/usePath.ts

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,36 @@
11
import { ElMessageBox } from 'element-plus'
22
import { onMounted, reactive, ref } from 'vue'
33

4+
import useHistory from '@/hooks/useHistory'
5+
46
export default function usePath() {
7+
const open = ref(false)
58
const view = reactive<{ path: string; diff: boolean }[]>([])
69
const active = ref(0)
710

11+
const history = useHistory<{ path: string }>({ key: 'PATH_HISTORY', id: 'path' })
12+
813
onMounted(async () => {
914
const query = new URLSearchParams(window.location.search).get('path') || ''
1015
if (query) {
11-
view.push({ path: query, diff: false })
16+
add(query)
1217
} else {
13-
add(true)
18+
open.value = true
1419
}
1520
})
1621

17-
const add = async (force?: boolean) => {
18-
const value = await ElMessageBox.prompt(
19-
'部分文件可在文件管理中双击文件进行编辑,详见应用介绍',
20-
'请输入文件路径',
21-
{
22-
showClose: false,
23-
closeOnClickModal: false,
24-
closeOnPressEscape: false,
25-
closeOnHashChange: false,
26-
showCancelButton: !force,
27-
confirmButtonText: '确认',
28-
cancelButtonText: '取消',
29-
inputPlaceholder: '不存在的文件路径在编辑后可新增并保存',
30-
},
31-
)
32-
.then(({ value }) => value)
33-
.catch(() => '')
34-
35-
if (value) {
36-
const index = view.findIndex((i) => i.path === value)
22+
const add = async (path: string) => {
23+
if (path) {
24+
const index = view.findIndex((i) => i.path === path)
3725
if (index > -1) {
3826
active.value = index
3927
} else {
40-
active.value = view.push({ path: value, diff: false }) - 1
28+
active.value = view.push({ path, diff: false }) - 1
4129
}
30+
history.add({ path })
4231
}
32+
33+
open.value = false
4334
}
4435

4536
const remove = async (index: number) => {
@@ -67,5 +58,5 @@ export default function usePath() {
6758
}
6859
}
6960

70-
return { view, active, add, remove }
61+
return { open, view, active, history, add, remove }
7162
}

0 commit comments

Comments
 (0)