Your Name 3 år sedan
förälder
incheckning
81e8f75e0b
6 ändrade filer med 71 tillägg och 91 borttagningar
  1. 2
    1
      package.json
  2. 36
    43
      src/components/ContextMenu.vue
  3. 8
    25
      src/components/SubMenu.vue
  4. 10
    22
      src/layouts/components/SiderBar.vue
  5. 3
    0
      src/main.js
  6. 12
    0
      yarn.lock

+ 2
- 1
package.json Visa fil

@@ -16,7 +16,8 @@
16 16
     "js-base64": "^3.7.2",
17 17
     "nprogress": "^0.2.0",
18 18
     "vue": "^3.2.25",
19
-    "vue-router": "4"
19
+    "vue-router": "4",
20
+    "vue-simple-context-menu": "^4.0.4"
20 21
   },
21 22
   "devDependencies": {
22 23
     "@vitejs/plugin-vue": "^2.3.3",

+ 36
- 43
src/components/ContextMenu.vue Visa fil

@@ -1,65 +1,58 @@
1 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">
2
+  <vue-simple-context-menu
3
+    element-id="my-context-menu"
4
+    :options="contextMenuOptions"
5
+    :ref="el => contextMenuRef = el"
6
+    @option-clicked="optionClicked"
7
+  />
8
+  <a-modal v-model:visible="modelProps.visible" :title="modelProps.title" @ok="confirmNew">
14 9
     <a-input v-model:value="inputText" placeholder="请输入名称" />
15 10
   </a-modal>
16 11
 </template>
17 12
 
18 13
 <script setup>
19
-import { computed, ref } from 'vue'
20
-// import { useModel } from '@zjxpcyc/vue-tiny-store'
14
+import { reactive, ref } from 'vue'
21 15
 import eventBus from '@/utils/eventBus'
22 16
 
23
-const visible = ref(false)
17
+const modelProps = reactive({ visible: false, title: undefined })
24 18
 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 19
 
32
-const emit = defineEmits(['menuClick'])
20
+const menuRef = ref()
21
+const contextMenuRef = ref()
22
+const contextMenuOptions = [
23
+  { id: 'newFolder', name: '新建文件夹' },
24
+  { id: 'newFile', name: '新建文件' },
25
+]
26
+const optionRef = ref()
33 27
 
34
-const confirmNew = () => {
35
-  const inputValue = inputText.value
28
+const emit = defineEmits(['newFile', 'newFolder'])
36 29
 
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
30
+const onContextMenu = ({ event, menu }) => {
31
+  contextMenuRef.value.showMenu(event)
32
+  menuRef.value = menu
49 33
 }
50 34
 
51
-const handleMenu = (e) => {
52
-  menuKey.value = e.key
53
-  visible.value = true
54
-  // 主要是为了清除样式, 但是暂时不起作用, 不知道为啥
55
-  selectedKeys.value = []
56
-  emit('menuClick')
35
+const optionClicked = (event) => {
36
+  modelProps.visible = true
37
+  modelProps.title = event.option.name
38
+  optionRef.value = event.option
57 39
 }
58 40
 
41
+const confirmNew = () => {
42
+  const option = optionRef.value
43
+  const data = { menu: menuRef.value, name: inputText.value }
44
+  emit(option.id, data)
45
+  modelProps.visible = false
46
+  inputText.value = undefined
47
+}
48
+
49
+eventBus.addEventListener('menu.contextMenu', onContextMenu)
50
+
59 51
 </script>
60 52
 
61 53
 <style lang="less" scoped>
62
-.content-menu-box {
54
+.my-context-menu {
63 55
   width: 200px;
56
+  background-color: #fff;
64 57
 }
65 58
 </style>

+ 8
- 25
src/components/SubMenu.vue Visa fil

@@ -4,18 +4,13 @@
4 4
       v-if="menu.type === 'dir'"
5 5
       :key="`/@@dir@@/${menu.path}`"
6 6
     >
7
-      <template #title>
8
-        <a-tooltip v-model:visible="tipVisible" trigger="no-trigger" placement="bottom" overlayClassName="menu-tooltip">
9
-          <template #title>
10
-            <ContextMenuVue @menuClick="tipVisible = false" />
11
-          </template>
12
-          <div class="dir-context-menu" @contextmenu.stop="handleContextMenu(`/@@dir@@/${menu.path}`)">
13
-            {{menu.name}}
14
-          </div>
15
-        </a-tooltip>
7
+      <template #title>        
8
+        <div class="dir-context-menu" @contextmenu.prevent.stop="event => onContextMenu(event, menu)">
9
+          {{menu.name}}
10
+        </div>
16 11
       </template>
17 12
       <template v-if="menu.children">
18
-        <SubMenu :menus="menu.children" :sub-menu="SubMenu" @contextfolder="handleContextMenu" />
13
+        <SubMenu :menus="menu.children" :sub-menu="SubMenu" />
19 14
       </template>
20 15
     </a-sub-menu>
21 16
     <a-menu-item v-else :key="`/@@file@@/${menu.path}`">{{ menu.name }}</a-menu-item>
@@ -23,9 +18,7 @@
23 18
 </template>
24 19
 
25 20
 <script setup>
26
-import { ref } from 'vue'
27
-import ContextMenuVue from './ContextMenu.vue';
28
-
21
+import eventBus from '@/utils/eventBus'
29 22
 const props = defineProps({
30 23
   menus: {
31 24
     type: Array,
@@ -34,20 +27,10 @@ const props = defineProps({
34 27
   subMenu: undefined,
35 28
 })
36 29
 
37
-const emit = defineEmits([ 'contextfolder' ])
38
-
39 30
 const SubMenu = props.subMenu
40 31
 
41
-const tipVisible = ref(false)
42
-
43
-const handleContextMenu = (key) => {
44
-  tipVisible.value = true
45
-
46
-  if (Array.isArray(key)) {
47
-    emit('contextfolder', key)
48
-  } else {
49
-    emit('contextfolder', [key])
50
-  }
32
+const onContextMenu = (event, menu) => {
33
+  eventBus.dispatchEvent('menu.contextMenu', { event, menu })
51 34
 }
52 35
 
53 36
 </script>

+ 10
- 22
src/layouts/components/SiderBar.vue Visa fil

@@ -10,22 +10,19 @@
10 10
     >
11 11
       <a-menu-item-group key="g1">
12 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>
13
+          <div>我的日记</div>
19 14
         </template>
20 15
       </a-menu-item-group>
21
-      <SubMenu :menus="fileTree" :sub-menu="SubMenu" @contextfolder="handleOpenChange"></SubMenu>
16
+      <SubMenu :menus="fileTree" :sub-menu="SubMenu"></SubMenu>
22 17
     </a-menu>
18
+    <ContextMenu :newFile="createNewFile" :newFolder="createNewFolder" />
23 19
   </div>
24 20
 </template>
25 21
 
26 22
 <script setup>
23
+import { ref } from 'vue'
27 24
 import { useModel } from '@zjxpcyc/vue-tiny-store'
28
-import ContextMenuVue from '@/components/ContextMenu.vue';
25
+import ContextMenu from '@/components/ContextMenu.vue';
29 26
 import SubMenu from '@/components/SubMenu.vue';
30 27
 import eventBus from '@/utils/eventBus'
31 28
 
@@ -36,6 +33,7 @@ const props = defineProps({
36 33
   }
37 34
 })
38 35
 
36
+
39 37
 const { user } = useModel('user')
40 38
 const { curMenu, menus, getMenus } = useModel('menu')
41 39
 const { fileArr, fileTree, getNote, getFiles } = useModel('note')
@@ -51,10 +49,6 @@ if (!fileTree || !fileTree.length) {
51 49
 const handleMenu = (e) => {
52 50
   const menuId = e.key
53 51
   const path = menuId.replace('/@@file@@/', '')
54
-
55
-  // const note = fileArr.filter(x => x.name === path)[0]
56
-  // curMenu.value = menu
57
-
58 52
   getNote(user, path)
59 53
 }
60 54
 
@@ -63,16 +57,12 @@ const handleOpenChange = (keys) => {
63 57
   if (!menuId) return;
64 58
 
65 59
   const path = menuId.replace('/@@dir@@/', '')
66
-
67
-  // const menu = getDeep(menus, path, 'dir');
68
-  // curMenu.value = menu
69
-
70 60
   getFiles(user, path, repo)
71 61
 }
72 62
 
73 63
 // 创建新文件
74
-const createNewFile = (newFileName) => {
75
-  const parentPath = curMenu.value ? curMenu.value.path : undefined
64
+const createNewFile = (parentMenu, newFileName) => {
65
+  const parentPath = parentMenu.path
76 66
   const newFilePath = parentPath ? `${parentPath}/${newFileName}.html` : `${newFileName}.html`
77 67
 
78 68
   newFile('又是一篇崭新的日记...', newFilePath, user).then(() => {
@@ -88,8 +78,8 @@ const createNewFile = (newFileName) => {
88 78
 }
89 79
 
90 80
 // 创建新目录
91
-const createNewFolder = (newFolderName) => {
92
-  const parentPath = curMenu.value ? curMenu.value.path : undefined
81
+const createNewFolder = (parentMenu, newFolderName) => {
82
+  const parentPath = parentMenu.path
93 83
   const newFilePath = parentPath ? `${parentPath}/${newFolderName}` : newFolderName
94 84
 
95 85
   newFolder(newFilePath, user).then(() => {
@@ -104,6 +94,4 @@ const createNewFolder = (newFolderName) => {
104 94
   })
105 95
 }
106 96
 
107
-eventBus.addEventListener('menu.newFile', createNewFile)
108
-eventBus.addEventListener('menu.newFolder', createNewFolder)
109 97
 </script>

+ 3
- 0
src/main.js Visa fil

@@ -1,5 +1,7 @@
1 1
 import { createApp } from 'vue'
2 2
 import Antd from 'ant-design-vue';
3
+import VueSimpleContextMenu from 'vue-simple-context-menu';
4
+import 'vue-simple-context-menu/dist/vue-simple-context-menu.css';
3 5
 import 'ant-design-vue/dist/antd.css';
4 6
 import 'nprogress/nprogress.css'
5 7
 import App from './App.vue'
@@ -11,4 +13,5 @@ const app = createApp(App)
11 13
 app.use(store)
12 14
 app.use(router)
13 15
 app.use(Antd)
16
+app.component('vue-simple-context-menu', VueSimpleContextMenu);
14 17
 app.mount('#app')

+ 12
- 0
yarn.lock Visa fil

@@ -284,6 +284,11 @@ chokidar@^3.5.3:
284 284
   optionalDependencies:
285 285
     fsevents "~2.3.2"
286 286
 
287
+click-outside-vue3@^4.0.1:
288
+  version "4.0.1"
289
+  resolved "https://registry.yarnpkg.com/click-outside-vue3/-/click-outside-vue3-4.0.1.tgz#81a6ac01696b301764b42db6fdbdf28e7cd8ef95"
290
+  integrity sha512-sbplNecrup5oGqA3o4bo8XmvHRT6q9fvw21Z67aDbTqB9M6LF7CuYLTlLvNtOgKU6W3zst5H5zJuEh4auqA34g==
291
+
287 292
 combined-stream@^1.0.8:
288 293
   version "1.0.8"
289 294
   resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@@ -945,6 +950,13 @@ vue-router@4:
945 950
   dependencies:
946 951
     "@vue/devtools-api" "^6.0.0"
947 952
 
953
+vue-simple-context-menu@^4.0.4:
954
+  version "4.0.4"
955
+  resolved "https://registry.yarnpkg.com/vue-simple-context-menu/-/vue-simple-context-menu-4.0.4.tgz#97aff25ee0ae0f82c0049797fdd60abbc3460b8d"
956
+  integrity sha512-Kn6rTXzKHpdTsPoKpBUQC4K+iZxpYiDU04BbGOgLuX/jLFIA7arzIstOp3+tFoV5JaWrjxGPLAuj2BAf8/G4pQ==
957
+  dependencies:
958
+    click-outside-vue3 "^4.0.1"
959
+
948 960
 vue-types@^3.0.0:
949 961
   version "3.0.2"
950 962
   resolved "https://registry.yarnpkg.com/vue-types/-/vue-types-3.0.2.tgz#ec16e05d412c038262fc1efa4ceb9647e7fb601d"