diff --git a/web/src/assets/icon-font/iconfont.css b/web/src/assets/icon-font/iconfont.css index 2f25af7d..de977d30 100644 --- a/web/src/assets/icon-font/iconfont.css +++ b/web/src/assets/icon-font/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 2479351 */ - src: url('iconfont.woff2?t=1697073602349') format('woff2'), - url('iconfont.woff?t=1697073602349') format('woff'), - url('iconfont.ttf?t=1697073602349') format('truetype'); + src: url('iconfont.woff2?t=1709091401707') format('woff2'), + url('iconfont.woff?t=1709091401707') format('woff'), + url('iconfont.ttf?t=1709091401707') format('truetype'); } .iconfont { @@ -13,6 +13,10 @@ -moz-osx-font-smoothing: grayscale; } +.iconwenjian1:before { + content: "\e69f"; +} + .icondodeparent:before { content: "\e70f"; } diff --git a/web/src/assets/icon-font/iconfont.ttf b/web/src/assets/icon-font/iconfont.ttf index f24f96b8..e65ff59a 100644 Binary files a/web/src/assets/icon-font/iconfont.ttf and b/web/src/assets/icon-font/iconfont.ttf differ diff --git a/web/src/assets/icon-font/iconfont.woff b/web/src/assets/icon-font/iconfont.woff index 013d113c..577f3102 100644 Binary files a/web/src/assets/icon-font/iconfont.woff and b/web/src/assets/icon-font/iconfont.woff differ diff --git a/web/src/assets/icon-font/iconfont.woff2 b/web/src/assets/icon-font/iconfont.woff2 index 04194e88..b4a7f5da 100644 Binary files a/web/src/assets/icon-font/iconfont.woff2 and b/web/src/assets/icon-font/iconfont.woff2 differ diff --git a/web/src/lang/en_us.js b/web/src/lang/en_us.js index 09c3df7a..28b40d6c 100644 --- a/web/src/lang/en_us.js +++ b/web/src/lang/en_us.js @@ -264,7 +264,8 @@ export default { fileContentError: 'File content error', fileOpenFailed: 'File open failed', defaultFileName: 'Mind map', - creatingTip: 'Creating file' + creatingTip: 'Creating file', + directory: 'Directory' }, edit: { newFeatureNoticeTitle: 'New feature reminder', diff --git a/web/src/lang/zh_cn.js b/web/src/lang/zh_cn.js index 7896a1e2..fa7458c6 100644 --- a/web/src/lang/zh_cn.js +++ b/web/src/lang/zh_cn.js @@ -260,7 +260,8 @@ export default { fileContentError: '文件内容有误', fileOpenFailed: '文件打开失败', defaultFileName: '思维导图', - creatingTip: '正在创建文件' + creatingTip: '正在创建文件', + directory: '目录' }, edit: { newFeatureNoticeTitle: '新特性提醒', diff --git a/web/src/pages/Edit/components/Toolbar.vue b/web/src/pages/Edit/components/Toolbar.vue index 0ea11401..4c126971 100644 --- a/web/src/pages/Edit/components/Toolbar.vue +++ b/web/src/pages/Edit/components/Toolbar.vue @@ -26,12 +26,16 @@
+
+ + {{ $t('toolbar.directory') }} +
{{ $t('toolbar.newFile') }}
- + {{ $t('toolbar.openFile') }}
@@ -42,10 +46,76 @@ {{ $t('toolbar.import') }}
-
+
{{ $t('toolbar.export') }}
+ +
+
+
+ {{ rootDirName ? '/' + rootDirName : '' }} +
+
+
+
+
+
+
+ + +
+ + {{ node.label }} +
+
+ 编辑 + 导入 +
+
+
+
+
@@ -54,7 +124,7 @@ - + @@ -112,7 +182,15 @@ export default { horizontalList: [], verticalList: [], showMoreBtn: true, - popoverShow: false + popoverShow: false, + fileTreeProps: { + label: 'name', + children: 'children', + isLeaf: 'leaf' + }, + fileTreeVisible: false, + rootDirName: '', + fileTreeExpand: true } }, computed: { @@ -178,6 +256,76 @@ export default { }, 1000) }, + // 加载本地文件树 + async loadFileTreeNode(node, resolve) { + try { + let dirHandle + if (node.level === 0) { + dirHandle = await window.showDirectoryPicker() + this.rootDirName = dirHandle.name + } else { + dirHandle = node.data.handle + } + const list = [] + for await (const [key, value] of dirHandle.entries()) { + const isFile = value.kind === 'file' + if (isFile && !/\.(smm|xmind|md|json)$/.test(value.name)) { + continue + } + const enableEdit = isFile && /\.smm$/.test(value.name) + list.push({ + id: key, + name: value.name, + type: value.kind, + handle: value, + leaf: isFile, + enableEdit + }) + } + resolve(list) + } catch (error) { + console.log(error) + this.fileTreeVisible = false + resolve([]) + if (error.toString().includes('aborted')) { + return + } + this.$message.warning(this.$t('toolbar.notSupportTip')) + } + }, + + // 扫描本地文件夹 + openDirectory() { + this.fileTreeVisible = false + this.fileTreeExpand = true + this.rootDirName = '' + this.$nextTick(() => { + this.fileTreeVisible = true + }) + }, + + // 编辑指定文件 + editLocalFile(data) { + if (data.handle) { + fileHandle = data.handle + this.readFile() + } + }, + + // 导入指定文件 + async importLocalFile(data) { + try { + const file = await data.handle.getFile() + this.$refs.ImportRef.onChange({ + raw: file, + name: file.name + }) + this.$refs.ImportRef.confirm() + } catch (error) { + console.log(error) + } + }, + // 打开本地文件 async openLocalFile() { try { @@ -325,6 +473,43 @@ export default { color: hsla(0, 0%, 100%, 0.9); .toolbarBlock { background-color: #262a2e; + + .fileTreeBox { + background-color: #262a2e; + + /deep/ .el-tree { + background-color: #262a2e; + + &.el-tree--highlight-current { + .el-tree-node.is-current > .el-tree-node__content { + background-color: hsla(0, 0%, 100%, 0.05) !important; + } + } + + .el-tree-node:focus > .el-tree-node__content { + background-color: hsla(0, 0%, 100%, 0.05) !important; + } + + .el-tree-node__content:hover, + .el-upload-list__item:hover { + background-color: hsla(0, 0%, 100%, 0.02) !important; + } + } + + .fileTreeWrap { + .customTreeNode { + .treeNodeInfo { + color: #fff; + } + + .treeNodeBtnList { + .el-button { + padding: 7px 5px; + } + } + } + } + } } .toolbarBtn { @@ -369,10 +554,96 @@ export default { border: 1px solid rgba(0, 0, 0, 0.06); margin-right: 20px; flex-shrink: 0; + position: relative; &:last-of-type { margin-right: 0; } + + .fileTreeBox { + position: absolute; + left: 0; + top: 68px; + width: 100%; + height: 30px; + background-color: #fff; + padding: 12px 5px; + padding-top: 0; + display: flex; + flex-direction: column; + overflow: hidden; + border-radius: 5px; + min-width: 200px; + + &.expand { + height: 300px; + + .fileTreeWrap { + visibility: visible; + } + } + + .fileTreeToolbar { + width: 100%; + height: 30px; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid #e9e9e9; + margin-bottom: 12px; + padding-left: 12px; + + .fileTreeName { + } + + .fileTreeActionList { + .btn { + font-size: 18px; + margin-left: 12px; + cursor: pointer; + } + } + } + + .fileTreeWrap { + width: 100%; + height: 100%; + overflow: auto; + visibility: hidden; + + .customTreeNode { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 13px; + padding-right: 5px; + + .treeNodeInfo { + display: flex; + align-items: center; + + .treeNodeIcon { + margin-right: 5px; + opacity: 0.7; + } + + .treeNodeName { + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + + .treeNodeBtnList { + display: flex; + align-items: center; + } + } + } + } } .toolbarBtn {