Your Name 3 anni fa
parent
commit
09530a9756

+ 65
- 0
src/components/ContextMenu.vue Vedi File

@@ -0,0 +1,65 @@
1
+<template>
2
+  <div class="content-menu-box">
3
+    <a-menu @click="handleMenu" v-model:selectedKeys="selectedKeys">
4
+      <a-menu-item key="save">
5
+        新建文件
6
+      </a-menu-item>
7
+      <a-menu-divider />
8
+      <a-menu-item key="newfolder">
9
+        新建文件夹
10
+      </a-menu-item>
11
+    </a-menu>
12
+  </div>
13
+  <a-modal v-model:visible="visible" title="新建" @ok="confirmNew">
14
+    <a-input v-model:value="inputText" placeholder="请输入名称" />
15
+  </a-modal>
16
+</template>
17
+
18
+<script setup>
19
+import { computed, ref } from 'vue'
20
+// import { useModel } from '@zjxpcyc/vue-tiny-store'
21
+import eventBus from '@/utils/eventBus'
22
+
23
+const visible = ref(false)
24
+const inputText = ref()
25
+const menuKey = ref()
26
+const selectedKeys = ref([])
27
+// const { curMenu } = useModel('menu')
28
+// const saveDisabledItem = computed(() => {
29
+//   return !curMenu.value || curMenu.value.type !== 'file'
30
+// })
31
+
32
+const emit = defineEmits(['menuClick'])
33
+
34
+const confirmNew = () => {
35
+  const inputValue = inputText.value
36
+
37
+  switch (menuKey.value) {
38
+    case 'save':
39
+      eventBus.dispatchEvent('menu.newFile', inputValue)
40
+      break;
41
+    case 'newfolder':
42
+      eventBus.dispatchEvent('menu.newFolder', inputValue)
43
+      break;
44
+    default:
45
+      break;
46
+  }
47
+  visible.value = false
48
+  inputText.value = undefined
49
+}
50
+
51
+const handleMenu = (e) => {
52
+  menuKey.value = e.key
53
+  visible.value = true
54
+  // 主要是为了清除样式, 但是暂时不起作用, 不知道为啥
55
+  selectedKeys.value = []
56
+  emit('menuClick')
57
+}
58
+
59
+</script>
60
+
61
+<style lang="less" scoped>
62
+.content-menu-box {
63
+  width: 200px;
64
+}
65
+</style>

+ 42
- 2
src/components/SubMenu.vue Vedi File

@@ -3,10 +3,19 @@
3 3
     <a-sub-menu
4 4
       v-if="menu.type === 'dir'"
5 5
       :key="`/@@dir@@/${menu.path}`"
6
-      :title="menu.name"
7 6
     >
7
+      <template #title>
8
+        <a-tooltip v-model:visible="tipVisible" trigger="contextmenu" placement="bottom" overlayClassName="menu-tooltip">
9
+          <template #title>
10
+            <ContextMenuVue @menuClick="tipVisible = false" />
11
+          </template>
12
+          <div @contextmenu="handleContextMenu(`/@@dir@@/${menu.path}`)">
13
+            {{menu.name}}
14
+          </div>
15
+          </a-tooltip>
16
+      </template>
8 17
       <template v-if="menu.children">
9
-        <SubMenu :menus="menu.children" :sub-menu="SubMenu" />
18
+        <SubMenu :menus="menu.children" :sub-menu="SubMenu" @contextfolder="handleContextMenu" />
10 19
       </template>
11 20
     </a-sub-menu>
12 21
     <a-menu-item v-else :key="`/@@file@@/${menu.path}`">{{ menu.name }}</a-menu-item>
@@ -14,6 +23,8 @@
14 23
 </template>
15 24
 
16 25
 <script setup>
26
+import { ref } from 'vue'
27
+import ContextMenuVue from './ContextMenu.vue';
17 28
 
18 29
 const props = defineProps({
19 30
   menus: {
@@ -23,6 +34,35 @@ const props = defineProps({
23 34
   subMenu: undefined,
24 35
 })
25 36
 
37
+const emit = defineEmits([ 'contextfolder' ])
38
+
26 39
 const SubMenu = props.subMenu
27 40
 
41
+const tipVisible = ref(false)
42
+
43
+const handleContextMenu = (key) => {
44
+  if (Array.isArray(key)) {
45
+    emit('contextfolder', key)
46
+  } else {
47
+    emit('contextfolder', [key])
48
+  }
49
+}
50
+
28 51
 </script>
52
+
53
+
54
+<style lang="less">
55
+.menu-tooltip {
56
+  .ant-tooltip-arrow-content {
57
+    background-color: transparent;
58
+  }
59
+  
60
+  .ant-tooltip-inner {
61
+    padding: 0;
62
+    background: transparent;
63
+    border: 1px solid rgba(0, 0, 0, 0.1);
64
+    border-radius: 8px;
65
+    overflow: hidden;
66
+  }
67
+}
68
+</style>

+ 2
- 2
src/layouts/NoteLayout.vue Vedi File

@@ -1,8 +1,8 @@
1 1
 <template>
2 2
   <a-layout>
3
-    <a-layout-header>
3
+    <!-- <a-layout-header>
4 4
       <Header />
5
-    </a-layout-header>
5
+    </a-layout-header> -->
6 6
     <a-layout>
7 7
       <a-layout-sider class="layout-sider" :width="siderWidth">
8 8
         <SiderBar :menu-style="menuStyle" />

+ 0
- 55
src/layouts/components/Header.vue Vedi File

@@ -1,64 +1,9 @@
1 1
 <template>
2 2
   <div></div>
3
-  <div>
4
-    <a-menu theme="dark" mode="horizontal" class="menu-navi" @click="handleMenu">
5
-      <a-menu-item key="save" :disabled="saveDisabledItem">
6
-        <template #icon>
7
-          <save-outlined />
8
-        </template>
9
-        保存
10
-      </a-menu-item>
11
-      <a-menu-item key="newfolder">
12
-        <template #icon>
13
-          <folder-add-outlined />
14
-        </template>
15
-        文件夹
16
-      </a-menu-item>
17
-    </a-menu>
18
-  </div>
19
-  <a-modal v-model:visible="newFolderVisible" title="新建文件夹" @ok="confirmNewFolder">
20
-    <a-input v-model:value="newFolderName" placeholder="请输入文件夹名称" />
21
-  </a-modal>
22 3
 </template>
23 4
 
24 5
 <script setup>
25
-import { computed, ref } from 'vue'
26
-import { useModel } from '@zjxpcyc/vue-tiny-store'
27
-import { SaveOutlined, FolderAddOutlined } from '@ant-design/icons-vue';
28
-import eventBus from '@/utils/eventBus'
29
-
30
-const newFolderVisible = ref(false)
31
-const newFolderName = ref()
32
-const { curMenu } = useModel('menu')
33
-const saveDisabledItem = computed(() => {
34
-  return !curMenu.value || curMenu.value.type !== 'file'
35
-})
36
-
37
-const confirmNewFolder = () => {
38
-  newFolderVisible.value = false
39
-  eventBus.dispatchEvent('menu.newFolder', newFolderName.value)
40
-  newFolderName.value = undefined
41
-}
42
-
43
-const handleMenu = (e) => {
44
-  switch (e.key) {
45
-    case 'save':
46
-      eventBus.dispatchEvent('menu.save')
47
-      break;
48
-    case 'newfolder':
49
-      newFolderVisible.value = true
50
-      break;
51
-    default:
52
-      break;
53
-  }
54
-}
55
-
56 6
 </script>
57 7
 
58 8
 <style lang="less" scoped>
59
-.menu-navi {
60
-  :deep(.ant-menu-item) {
61
-    color: #fff;
62
-  }
63
-}
64 9
 </style>

+ 24
- 2
src/layouts/components/SiderBar.vue Vedi File

@@ -8,13 +8,24 @@
8 8
       mode="inline"
9 9
       triggerSubMenuAction="click"
10 10
     >
11
-      <SubMenu :menus="menus" :sub-menu="SubMenu"></SubMenu>
11
+      <a-menu-item-group key="g1">
12
+        <template #title>
13
+          <a-tooltip trigger="contextmenu" placement="bottom" overlayClassName="menu-tooltip">
14
+            <template #title>
15
+              <ContextMenuVue />
16
+            </template>
17
+            <div>我的日记</div>
18
+          </a-tooltip>
19
+        </template>
20
+      </a-menu-item-group>
21
+      <SubMenu :menus="menus" :sub-menu="SubMenu" @contextfolder="handleOpenChange"></SubMenu>
12 22
     </a-menu>
13 23
   </div>
14 24
 </template>
15 25
 
16 26
 <script setup>
17 27
 import { useModel } from '@zjxpcyc/vue-tiny-store'
28
+import ContextMenuVue from '@/components/ContextMenu.vue';
18 29
 import SubMenu from '@/components/SubMenu.vue';
19 30
 import eventBus from '@/utils/eventBus'
20 31
 
@@ -28,6 +39,7 @@ const props = defineProps({
28 39
 const { user } = useModel('user')
29 40
 const { curMenu, menus, getMenus } = useModel('menu')
30 41
 const { getNote } = useModel('note')
42
+const { newFile, newFolder } = useModel('repo')
31 43
 
32 44
 if (!menus || !menus.length) {
33 45
   getMenus(user).then(res => {
@@ -80,7 +92,17 @@ const handleOpenChange = (keys) => {
80 92
 }
81 93
 
82 94
 const createNewFolder = (newFolderName) => {
83
-  console.log('----newFolderName---->', newFolderName)
95
+  if (!curMenu.value) return;
96
+
97
+  const path = curMenu.value.path + `/${newFolderName}`
98
+
99
+  newFolder(path, user).then(() => {
100
+    // 获取父级信息, 目的刷新当前目录
101
+    getMenus(user, curMenu.value.path).then(res => {
102
+      curMenu.value.children = res || []
103
+    })
104
+  })
105
+
84 106
 }
85 107
 
86 108
 

+ 8
- 0
src/store/model/repo.js Vedi File

@@ -31,6 +31,7 @@ export default function useRepo() {
31 31
     return request.post(`/api/v5/repos/${user.login}/${repo}`, data).then(res => Object.assign(repo, res))
32 32
   }
33 33
 
34
+  // 新增文件
34 35
   const newFile = (content, path, user, repo = 'my-note') => {
35 36
     const { access_token } = user.token
36 37
     const data = {
@@ -40,6 +41,12 @@ export default function useRepo() {
40 41
     }
41 42
     return request.post(`/api/v5/repos/${user.login}/${repo}/contents/${path}`, data)
42 43
   }
44
+  
45
+  // 新增目录, 其实就是新增一个 内容是 # 的 .gitignore 文件
46
+  const newFolder = (path, user, repo = 'my-note') => {
47
+    const filePath = `${path}/.gitignore`
48
+    return newFile('#', filePath, user, repo)
49
+  }
43 50
 
44 51
   return {
45 52
     repo,
@@ -47,5 +54,6 @@ export default function useRepo() {
47 54
     newRepo,
48 55
     newBranch,
49 56
     newFile,
57
+    newFolder,
50 58
   }
51 59
 }