文本编辑器加上目录导航
This commit is contained in:
parent
f93d3c944d
commit
caa1133b97
@ -247,4 +247,12 @@ export default {
|
||||
params
|
||||
})
|
||||
},
|
||||
// 根据path添加文件/文件夹
|
||||
addFile: function(params) {
|
||||
return request({
|
||||
url: '/addfile',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
86
src/components/Breadcrumb/FilePathNav.vue
Normal file
86
src/components/Breadcrumb/FilePathNav.vue
Normal file
@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<el-breadcrumb class="app-breadcrumb" separator="">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(item,index) in pathList" :key="item.path">
|
||||
<a v-if="index===0" class="home-link" @click.prevent="handleLink(item,index)"><svg-icon icon-class="home" style="font-size: 18px;"/></a>
|
||||
<!--<span v-if="index===pathList.length-1" class="no-redirect">{{ item.title }}</span>-->
|
||||
<!--<a v-if="index > 0 && index < pathList.length-1" @click.prevent="handleLink(item)">{{ item.title }}</a>-->
|
||||
<breadcrumb-file-path :pathList="pathList" :item="item" :index="index" @clickLink="handleLink"></breadcrumb-file-path>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
<script>
|
||||
import { strlen, substring10,substring } from '@/utils/number'
|
||||
import BreadcrumbFilePath from "@/components/Breadcrumb/BreadcrumbFilePath";
|
||||
export default {
|
||||
name: 'FilePathNav',
|
||||
components: {
|
||||
BreadcrumbFilePath
|
||||
},
|
||||
props: {
|
||||
path:{
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pathList: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
path(path){
|
||||
console.log('path', path)
|
||||
this.pathList = [{folder:'',path: '/'}]
|
||||
let list = path.split('/').filter((item)=>item.length>0)
|
||||
list.forEach((pathName,index)=>{
|
||||
const item = {
|
||||
folder: pathName,
|
||||
path: this.getPath(list,index)
|
||||
}
|
||||
this.pathList.push(item)
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
methods: {
|
||||
strLength(str) {
|
||||
return strlen(str)
|
||||
},
|
||||
substring10(str) {
|
||||
return substring10(str)
|
||||
},
|
||||
substring(str,n){
|
||||
return substring(str,n)
|
||||
},
|
||||
getPath(list,index){
|
||||
let path = '/'
|
||||
if(list && list.length > index){
|
||||
for (let i = 0; i <= index; i++) {
|
||||
path += list[i]+'/'
|
||||
}
|
||||
}
|
||||
return path
|
||||
},
|
||||
handleLink(item) {
|
||||
this.$emit('loadPath',item)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-breadcrumb.el-breadcrumb {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
line-height: 50px;
|
||||
margin-left: 8px;
|
||||
|
||||
.no-redirect {
|
||||
color: #97a8be;
|
||||
cursor: text;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-contextmenu ref="clickContextmenu" :theme="lightTheme?'default':'dark'" event-type="click">
|
||||
<v-contextmenu-item v-for="item of menus" :key="item.operation" @click="contextmenuClick(item.operation)">
|
||||
<svg-icon :icon-class="item.iconClass"></svg-icon>
|
||||
{{item.label}}
|
||||
</v-contextmenu-item>
|
||||
</v-contextmenu>
|
||||
|
||||
<v-contextmenu ref="contextmenu" :theme="lightTheme?'default':'dark'" @contextmenu="contextmenu">
|
||||
<v-contextmenu-item v-for="item of menus" :key="item.operation" @click="contextmenuClick(item.operation)">
|
||||
<svg-icon :icon-class="item.iconClass"></svg-icon>
|
||||
@ -10,7 +17,7 @@
|
||||
<el-button-group>
|
||||
<el-button :class="lightTheme?'light-button':'dark-button'" size="small" icon="el-icon-arrow-left" @click="upperLeve">上一级</el-button>
|
||||
<el-button :class="lightTheme?'light-button':'dark-button'" size="small" icon="el-icon-refresh" @click="refresh">刷新</el-button>
|
||||
<el-button :class="lightTheme?'light-button':'dark-button'" size="small" icon="el-icon-plus">新建</el-button>
|
||||
<el-button :class="lightTheme?'light-button':'dark-button'" size="small" icon="el-icon-plus" @click="newFileAndFolder" v-contextmenu:clickContextmenu>新建</el-button>
|
||||
<el-button :class="lightTheme?'light-button':'dark-button'" size="small" icon="el-icon-search">搜索</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
@ -19,7 +26,6 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import $ from 'jquery'
|
||||
import 'v-contextmenu/dist/index.css'
|
||||
import { iconClass,suffix } from '@/utils/file-type'
|
||||
import 'jquery.fancytree/dist/skin-win8/ui.fancytree.less';
|
||||
@ -40,17 +46,18 @@
|
||||
default: 500
|
||||
},
|
||||
directoryTreeData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
lightTheme: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
tree:{},
|
||||
currentPath: '/',
|
||||
contextData: {},
|
||||
rightClicking: false,
|
||||
menus: [],
|
||||
@ -80,6 +87,48 @@
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
initTree(treeData){
|
||||
const that = this
|
||||
this.tree = fancytree.createTree('#dir-tree', {
|
||||
extensions: ["edit"],
|
||||
icon: (event,data)=> this.icon(event,data),
|
||||
source: this.convert(treeData),
|
||||
lazyLoad: (event,data)=> this.lazyLoad(event,data),
|
||||
click: (event,data)=> this.click(event,data),
|
||||
dblclick: (event,data)=> this.dblclick(event,data),
|
||||
activate: (event,data)=> this.activate(event,data),
|
||||
createNode: (event,data)=> this.createNode(event,data),
|
||||
edit: {
|
||||
triggerStart: ["f2", "mac+enter"],
|
||||
beforeEdit: function(event, data){
|
||||
},
|
||||
edit: function(event, data){
|
||||
let intput = data.node.span.querySelector('.fancytree-title .fancytree-edit-input')
|
||||
let width = intput.style.width.substring(0,intput.style.width.length-2)
|
||||
intput.style.width = parseInt(width)+50+'px'
|
||||
},
|
||||
beforeClose: function(event, data){
|
||||
if( data.originalEvent.type === "mousedown" ) {
|
||||
data.originalEvent.preventDefault();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
save: function(event, data){
|
||||
if(data.node.data.path){
|
||||
that.nodeRename(data.input.val(), data.node.data, data.node)
|
||||
}else{
|
||||
that.createFile(data.input.val(), data.node.data, data.node)
|
||||
}
|
||||
return true;
|
||||
},
|
||||
close: function(event, data){
|
||||
if( data.save ) {
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
contextmenu(vnode){
|
||||
this.rightClicking = true
|
||||
const that = this
|
||||
@ -94,27 +143,45 @@
|
||||
if(this.contextData.isFolder){
|
||||
this.menus = this.folderMenus
|
||||
}else{
|
||||
this.menus = this.fileMenus
|
||||
if(this.contextData.isFolder === undefined){
|
||||
|
||||
}else{
|
||||
this.menus = this.fileMenus
|
||||
}
|
||||
}
|
||||
},
|
||||
// 菜单点击事件
|
||||
contextmenuClick(operation){
|
||||
let node = this.tree.getActiveNode()
|
||||
switch (operation) {
|
||||
case 'openFolder':
|
||||
console.log('openFolder',this.contextData)
|
||||
this.enterDir(this.contextData)
|
||||
break
|
||||
case 'remove':
|
||||
console.log('remove',this.contextData)
|
||||
this.delFile(this.contextData)
|
||||
break
|
||||
case 'rename':
|
||||
console.log('rename',this.contextData)
|
||||
this.tree.getActiveNode().editStart()
|
||||
break
|
||||
default:
|
||||
console.log('default',this.contextData)
|
||||
case 'addFile':
|
||||
this.editCreateNode(node,false)
|
||||
break
|
||||
case 'addFolder':
|
||||
this.editCreateNode(node,true)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
},
|
||||
editCreateNode(node,isFolder){
|
||||
if(node === null || node === undefined){
|
||||
this.tree.getRootNode().editCreateNode("child",{title:'',folder:isFolder})
|
||||
return
|
||||
}
|
||||
if(node.folder){
|
||||
node.editCreateNode("child",{title:'',folder:isFolder})
|
||||
}else{
|
||||
node.editCreateNode("after",{title:'',folder:isFolder})
|
||||
}
|
||||
},
|
||||
// 删除文件/文件夹
|
||||
@ -135,16 +202,13 @@
|
||||
})
|
||||
})
|
||||
},
|
||||
// 上级目录
|
||||
upperLeve(){
|
||||
let path = this.tree.rootNode.children[0].key
|
||||
let title = this.tree.rootNode.children[0].title
|
||||
if(path.endsWith(title)){
|
||||
path = path.substring(0,path.length-title.length)
|
||||
}
|
||||
if(path.length === 0){
|
||||
if(this.currentPath.length === 0){
|
||||
return
|
||||
}
|
||||
let pathList = this.currentPath.split('/')
|
||||
let title = pathList[pathList.length-2]
|
||||
let path = this.currentPath.substring(0,this.currentPath.length-title.length)
|
||||
api.upperLevelList({
|
||||
username: this.$store.state.user.name,
|
||||
path: path,
|
||||
@ -154,13 +218,17 @@
|
||||
},
|
||||
// 刷新当前目录
|
||||
refresh(){
|
||||
api.upperLevelList({
|
||||
api.listfiles({
|
||||
userId: this.$store.state.user.userId,
|
||||
username: this.$store.state.user.name,
|
||||
path: this.tree.rootNode.children[0].key,
|
||||
path: this.currentPath,
|
||||
}).then(res => {
|
||||
this.tree.reload(this.convert(res.data))
|
||||
})
|
||||
},
|
||||
newFileAndFolder(){
|
||||
this.menus = this.newFileMenus
|
||||
},
|
||||
//进入目录
|
||||
enterDir(node){
|
||||
let loading = this.$message({
|
||||
@ -177,18 +245,25 @@
|
||||
path: node.path,
|
||||
}).then(res => {
|
||||
loading.close()
|
||||
if(res.data.length === 0){
|
||||
this.currentPath = node.path+'/'
|
||||
}
|
||||
this.tree.reload(this.convert(res.data))
|
||||
}).catch(()=>{
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
loadTreeData(treeData,reLoad) {
|
||||
loadPath(data){
|
||||
data.name = data.title
|
||||
this.loadTreeData(data,true)
|
||||
},
|
||||
loadTreeData(treeData,reLoad,activeNodeData) {
|
||||
api.listfiles({
|
||||
userId: this.$store.state.user.userId,
|
||||
username: this.$store.state.user.name,
|
||||
path: treeData[0].path,
|
||||
path: treeData.path,
|
||||
}).then(res => {
|
||||
let oldname = treeData[0].name
|
||||
let oldname = treeData.name
|
||||
let data = res.data.map(doc => {
|
||||
if(oldname === doc.name){
|
||||
doc.active = true
|
||||
@ -201,47 +276,45 @@
|
||||
})
|
||||
if(reLoad){
|
||||
this.tree.reload(this.convert(data))
|
||||
if(activeNodeData){
|
||||
this.$emit('treeNodeClick', activeNodeData)
|
||||
}
|
||||
}else{
|
||||
this.initTree(this.convert(data))
|
||||
}
|
||||
})
|
||||
},
|
||||
initTree(treeData){
|
||||
const that = this
|
||||
this.tree = fancytree.createTree('#dir-tree', {
|
||||
extensions: ["edit"],
|
||||
icon: (event,data)=> this.icon(event,data),
|
||||
source: this.convert(treeData),
|
||||
lazyLoad: (event,data)=> this.lazyLoad(event,data),
|
||||
click: (event,data)=> this.click(event,data),
|
||||
dblclick: (event,data)=> this.dblclick(event,data),
|
||||
activate: (event,data)=> this.activate(event,data),
|
||||
createNode: (event,data)=> this.createNode(event,data),
|
||||
edit: {
|
||||
triggerStart: ["f2", "mac+enter"],
|
||||
beforeEdit: function(event, data){
|
||||
console.log(event.type, data);
|
||||
},
|
||||
edit: function(event, data){
|
||||
let intput = data.node.span.querySelector('.fancytree-title .fancytree-edit-input')
|
||||
let width = intput.style.width.substring(0,intput.style.width.length-2)
|
||||
intput.style.width = parseInt(width)+50+'px'
|
||||
},
|
||||
beforeClose: function(event, data){
|
||||
},
|
||||
save: function(event, data){
|
||||
that.nodeRename(data.input.val(), data.node.data, data.node)
|
||||
return true;
|
||||
},
|
||||
close: function(event, data){
|
||||
console.log(event.type, data);
|
||||
if( data.save ) {
|
||||
}
|
||||
return false
|
||||
}
|
||||
// 新建文件
|
||||
createFile(fileName,row,node){
|
||||
let parentPath = '/'
|
||||
if(node.parent.folder){
|
||||
parentPath = node.parent.data.path
|
||||
}else{
|
||||
let parent = node.parent.children[0].data
|
||||
if(parent.path){
|
||||
parentPath += parent.path.substring(0,parent.path.length-parent.name.length)
|
||||
}else{
|
||||
parentPath += this.currentPath
|
||||
}
|
||||
});
|
||||
console.log(this.tree.getActiveNode(),fancytree._extensions)
|
||||
}
|
||||
api.addFile({
|
||||
fileName: fileName,
|
||||
isFolder: node.folder,
|
||||
username: this.$store.state.user.name,
|
||||
parentPath: parentPath
|
||||
}).then((res)=>{
|
||||
let str = node.folder?'文件夹':'文件'
|
||||
this.$message.success(`新建${str}成功`)
|
||||
let activeNodeData = res.data
|
||||
// if(node.parent.folder){
|
||||
// activeNodeData = node.parent.data
|
||||
// activeNodeData.children = res.data
|
||||
// }
|
||||
let path = '/'+ activeNodeData.path.substring(0,activeNodeData.path.length-activeNodeData.name.length)
|
||||
this.loadTreeData({name: activeNodeData.name,path: path},true,activeNodeData)
|
||||
}).catch(()=>{
|
||||
node.remove()
|
||||
})
|
||||
},
|
||||
// 重命名
|
||||
nodeRename(newFileName, row, node) {
|
||||
@ -259,6 +332,8 @@
|
||||
if (row.suffix !== newExt) {
|
||||
this.$confirm(`您确定要将扩展名“.${row.suffix}”更改为“.${newExt}”吗?`,'提示',{
|
||||
type: 'warning',
|
||||
showClose: false,
|
||||
closeOnClickModal: false,
|
||||
confirmButtonText: `保持.${row.suffix}`,
|
||||
cancelButtonText: `使用.${newExt}`,
|
||||
}).then(()=>{
|
||||
@ -372,13 +447,20 @@
|
||||
activate(event, data){
|
||||
},
|
||||
createNode(event, data){
|
||||
if(data.node.key !== '_1'){
|
||||
if(data.node.statusNodeType !== 'nodata'){
|
||||
this.$refs.contextmenu.addRef({el:data.node.span,vnode: data.node.span})
|
||||
}else{
|
||||
data.node.span.querySelector('.fancytree-title').innerText = '无数据'
|
||||
}
|
||||
},
|
||||
convert(data){
|
||||
if(data && data.length >0){
|
||||
this.currentPath = data[0].path.substring(0,data[0].path.length - data[0].name.length)
|
||||
}
|
||||
if(this.currentPath.length === 0){
|
||||
this.currentPath = '/'
|
||||
}
|
||||
this.$emit('onLoadTreePath', this.currentPath)
|
||||
return data.map(doc => {
|
||||
doc.key = doc.path
|
||||
doc.title = doc.name
|
||||
|
||||
@ -1519,12 +1519,13 @@
|
||||
})
|
||||
// 使列表可拖拽
|
||||
this.rowDrop()
|
||||
this.fileListScrollTop = 0
|
||||
// 使列表滑到顶部
|
||||
if(!onLoad && !this.grid){
|
||||
console.log('使列表滑到顶部',this.$refs.fileListTable)
|
||||
//this.$refs.fileListTable.pagingScrollTopLeft()
|
||||
if(this.fileListScrollTop > 0){
|
||||
this.$refs.fileListTable.pagingScrollTopLeft()
|
||||
}
|
||||
}
|
||||
this.fileListScrollTop = 0
|
||||
},
|
||||
searchFile(key,onLoad) {
|
||||
if(key){
|
||||
|
||||
@ -36,7 +36,8 @@
|
||||
class="simtext-dialog"
|
||||
v-dialogDrag="{ dialogWidth: dialogWidth}">
|
||||
<div slot="title" class="simtext-header-title">
|
||||
<span class="title-name">{{file.name}}</span>
|
||||
<!--<span class="title-name">{{file.name}}</span>-->
|
||||
<span><file-path-nav class="title-name" :path="filePathNav" @loadPath="loadPath"></file-path-nav></span>
|
||||
<div class="title-extension">
|
||||
<el-button v-if="isShowUpdateBtn" @click="saveAll" :class="lightTheme?'':'dark-button'" size="small" :loading="updating">保存所有</el-button>
|
||||
<!-- <el-button @click="changePreviewMode">{{previewMode?'预览模式':'源码模式'}}</el-button> -->
|
||||
@ -49,7 +50,16 @@
|
||||
<div class="content">
|
||||
<div class="file-contents" :style="{width: contentsWidth+'px',height: editorHieght+31+'px'}">
|
||||
<div class="content-tree">
|
||||
<fancy-tree ref="fancTree" :contentsWidth="contentsWidth" :contentsHieght="editorHieght" v-if="directoryTreeData.length > 0" :lightTheme="lightTheme" :directoryTreeData="directoryTreeData" @treeNodeClick="treeNodeClick"></fancy-tree>
|
||||
<fancy-tree
|
||||
ref="fancTree"
|
||||
:contentsWidth="contentsWidth"
|
||||
:contentsHieght="editorHieght"
|
||||
:lightTheme="lightTheme"
|
||||
:directoryTreeData="directoryTreeData"
|
||||
@treeNodeClick="treeNodeClick"
|
||||
@onLoadTreePath="onLoadTreePath"
|
||||
>
|
||||
</fancy-tree>
|
||||
</div>
|
||||
</div>
|
||||
<div class="editor-resize" style="width: 3px;cursor: col-resize;"></div>
|
||||
@ -99,11 +109,12 @@
|
||||
import FileTree from"@/components/FileTree"
|
||||
import FancyTree from"@/components/FancyTree"
|
||||
import MessageDialog from "@/components/message/MessageDialog"
|
||||
import FilePathNav from '@/components/Breadcrumb/FilePathNav'
|
||||
|
||||
export default {
|
||||
name: "SimTextPreview",
|
||||
components: {
|
||||
MonacoEditor,FileTree,FancyTree,MessageDialog
|
||||
MonacoEditor,FileTree,FancyTree,MessageDialog,FilePathNav
|
||||
},
|
||||
props: {
|
||||
file: {
|
||||
@ -164,9 +175,10 @@
|
||||
border: '1px solid #565656!important',
|
||||
color: '#ffffff!important'
|
||||
},
|
||||
directoryTreeData: [],
|
||||
directoryTreeData: {},
|
||||
editableTabsValue: '1',
|
||||
editableTabs: [],
|
||||
filePathNav: '',
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -230,7 +242,7 @@
|
||||
username: this.$store.state.user.name
|
||||
}).then((res)=>{
|
||||
this.loading.close()
|
||||
this.directoryTreeData = [{name: res.data.name, isFolder: true, isLeaf: false, id: res.data.id, path: res.data.path}]
|
||||
this.directoryTreeData = {name: res.data.name, isFolder: true, isLeaf: false, id: res.data.id, path: res.data.path}
|
||||
this.textPreviewVisible = true
|
||||
this.content = res.data.contentText
|
||||
|
||||
@ -304,6 +316,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
loadPath(data){
|
||||
this.$refs.fancTree.loadPath(data)
|
||||
},
|
||||
onLoadTreePath(path){
|
||||
this.filePathNav = path
|
||||
},
|
||||
treeNodeClick(row) {
|
||||
if(row.isFolder){
|
||||
return
|
||||
@ -514,12 +532,18 @@
|
||||
if(fileContests){
|
||||
fileContests.setAttribute('data-theme', 'light')
|
||||
}
|
||||
if(header){
|
||||
header.setAttribute('data-theme', 'light')
|
||||
}
|
||||
}else{
|
||||
header.style.background = '#292929'
|
||||
header.style.color = '#fff'
|
||||
if(fileContests){
|
||||
fileContests.setAttribute('data-theme', 'dark')
|
||||
}
|
||||
if(header){
|
||||
header.setAttribute('data-theme', 'dark')
|
||||
}
|
||||
}
|
||||
},
|
||||
changePreviewMode() {
|
||||
@ -637,7 +661,7 @@
|
||||
}
|
||||
}
|
||||
.title-name {
|
||||
line-height: 40px;
|
||||
line-height: 34px;
|
||||
}
|
||||
.title-extension {
|
||||
float: right;
|
||||
@ -667,6 +691,19 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&[data-theme=dark] {
|
||||
.redirect{
|
||||
color: #f5f5f5;
|
||||
}
|
||||
.no-redirect {
|
||||
color: #b7b7b7;
|
||||
}
|
||||
.home-link {
|
||||
color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.el-dialog__body {
|
||||
padding: 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user