|
|
|
@ -6,7 +6,8 @@ |
|
|
|
<!-- 选择服务器 --> |
|
|
|
<select class="selbox" name="fsip" ref="fsip" @change="changeSer"> |
|
|
|
<option value="0">请选择源服务器</option> |
|
|
|
<option v-for="item in uslist" :value="item.addr+':'+item.port">{{ item.addr+':'+item.port }}</option> |
|
|
|
<option v-for="item in uslist" :value="item.addr + ':' + item.port">{{ item.addr + ':' + item.port }} |
|
|
|
</option> |
|
|
|
</select> |
|
|
|
<input name="path" class="inputbox" type="text" placeholder="/" autocomplete="off" v-model="fspath"> |
|
|
|
<button @click="getFlist">Go</button> |
|
|
|
@ -14,16 +15,21 @@ |
|
|
|
</div> |
|
|
|
<div class="sflist"> |
|
|
|
<ul> |
|
|
|
<li v-for="item in fsclist" :key="item"> |
|
|
|
<li v-for="item in fsclist" :key="item" @contextmenu.prevent="showMenu" @click="hideMenu"> |
|
|
|
<input type="checkbox" :value="item.path" class="sfchkbox" /> |
|
|
|
<a class="haschild" @click="goIntoDir(item.path, 1)" v-if="item.isdir">{{ item.path }}</a> |
|
|
|
<span v-else>{{ item.path }}</span> |
|
|
|
<!-- |
|
|
|
<div class="sflfunc"> |
|
|
|
<a>发送</a> |
|
|
|
</div> --> |
|
|
|
</li> |
|
|
|
</ul> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="tips"> |
|
|
|
<span v-if="fsclist.length > 0"> 服务器:{{this.$refs.fsip.value}} 路径:{{fspath}} ,文件数量:{{ fsclist.length }}</span> |
|
|
|
<span v-if="fsclist.length > 0"> 服务器:{{ this.$refs.fsip.value }} 路径:{{ fspath }} ,文件数量:{{ fsclist.length |
|
|
|
}}</span> |
|
|
|
<span v-else>当前服务器:{{ fsip }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
@ -33,7 +39,8 @@ |
|
|
|
<!-- 选择服务器 --> |
|
|
|
<select class="selbox" name="ssip" ref="ssip"> |
|
|
|
<option value="0">请选择源服务器</option> |
|
|
|
<option v-for="item in uslist" :value="item.addr+':'+item.port">{{ item.addr+':'+item.port }}</option> |
|
|
|
<option v-for="item in uslist" :value="item.addr + ':' + item.port">{{ item.addr + ':' + item.port }} |
|
|
|
</option> |
|
|
|
</select> |
|
|
|
<input name="path" class="inputbox" type="text" placeholder="/" autocomplete="off" v-model="sspath"> |
|
|
|
<button @click="getSflist">GO</button> |
|
|
|
@ -54,6 +61,18 @@ |
|
|
|
<span v-else>当前服务器:{{ ssip }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 右键菜单 --> |
|
|
|
<div class="sftrans" v-if="isMenuVisible" @contextmenu.prevent :style="{ top: menuTop + 'px', left: menuLeft + 'px' }"> |
|
|
|
<ul class="sfbcon"> |
|
|
|
<li><span href="javascript:void(0)" @click="handleMenuAction('upload')">同步文件</span></li> |
|
|
|
<li><span href="javascript:void(0)" @click="handleMenuAction('download')">压缩下载</span></li> |
|
|
|
<li class="divider"></li> |
|
|
|
<li><span href="javascript:void(0)" @click="handleMenuAction('delete')">删除文件</span></li> |
|
|
|
</ul> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
@ -71,16 +90,32 @@ export default { |
|
|
|
uslist: [], //使用中的服务器 |
|
|
|
fspath: '/', // 第一个服务器的路径 |
|
|
|
sspath: '/', // 第二个服务器的路径 |
|
|
|
|
|
|
|
isMenuVisible: true, // 菜单是否可见 |
|
|
|
menuTop: 0, // 菜单顶部位置 |
|
|
|
menuLeft: 0, // 菜单左侧位置 |
|
|
|
} |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
// 点击文档其他区域隐藏菜单 |
|
|
|
document.addEventListener('click', (event) => { |
|
|
|
//避免快速点击时的冲突 |
|
|
|
if(this.isMenuVisible){ |
|
|
|
this.hideMenu() |
|
|
|
} |
|
|
|
}) |
|
|
|
// 使用中的服务器 |
|
|
|
SerlistInUsing().then(res => { |
|
|
|
this.uslist = res.data; |
|
|
|
}) |
|
|
|
|
|
|
|
}, |
|
|
|
beforeMount() { |
|
|
|
// 移除事件监听 |
|
|
|
document.removeEventListener('click', this.hideMenu); |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
|
|
|
|
// 获取第一个服务器的文件列表 |
|
|
|
getFlist() { |
|
|
|
// 获取第一个服务器 |
|
|
|
@ -110,16 +145,12 @@ export default { |
|
|
|
let npath, sel |
|
|
|
if (nflag == 1) { |
|
|
|
sel = this.$refs.fsip.value |
|
|
|
// if(this.fspath == path){ |
|
|
|
// this.fspath = '/' |
|
|
|
// } |
|
|
|
// 拼装url |
|
|
|
if (this.fspath == '/') { |
|
|
|
npath = '/' + path |
|
|
|
} else { |
|
|
|
npath = this.fspath + '/' + path |
|
|
|
} |
|
|
|
// npath = this.fspath== '/' ? "/"+path : this.fspath + path |
|
|
|
} |
|
|
|
if (nflag == 2) { |
|
|
|
sel = this.$refs.ssip.value |
|
|
|
@ -132,13 +163,10 @@ export default { |
|
|
|
} else { |
|
|
|
npath = this.sspath + '/' + path |
|
|
|
} |
|
|
|
// npath = this.sspath + path+"/" |
|
|
|
// npath = this.sspath == '/' ? "/"+path : this.fspath + path |
|
|
|
} |
|
|
|
let rrarr = this.preIp(sel) |
|
|
|
// ip转为base64 |
|
|
|
let ip = btoa(rrarr[0]) |
|
|
|
console.log(npath) |
|
|
|
this.queryFlist(ip, rrarr[1], npath, nflag) |
|
|
|
}, |
|
|
|
// 查询内容 |
|
|
|
@ -202,8 +230,46 @@ export default { |
|
|
|
// 调用方法 |
|
|
|
this.getSflist() |
|
|
|
} |
|
|
|
}, |
|
|
|
// 右键菜单内容 |
|
|
|
showMenu(event) { |
|
|
|
console.log(event) |
|
|
|
// 计算菜单位置(基于点击坐标) |
|
|
|
this.menuTop = event.clientY; |
|
|
|
this.menuLeft = event.clientX; |
|
|
|
|
|
|
|
// 确保菜单不会超出视口 |
|
|
|
this.adjustMenuPosition(); |
|
|
|
|
|
|
|
// 显示菜单 |
|
|
|
this.isMenuVisible = true; |
|
|
|
}, |
|
|
|
// 隐藏右键菜单 |
|
|
|
hideMenu() { |
|
|
|
this.isMenuVisible = false; |
|
|
|
}, |
|
|
|
// 调整菜单位置,避免超出视口 |
|
|
|
adjustMenuPosition() { |
|
|
|
const menuWidth = 200; // 菜单宽度(px) |
|
|
|
const menuHeight = 160; // 菜单高度(px) |
|
|
|
|
|
|
|
// 右侧超出视口时向左调整 |
|
|
|
if (this.menuLeft + menuWidth > window.innerWidth) { |
|
|
|
this.menuLeft = window.innerWidth - menuWidth; |
|
|
|
} |
|
|
|
|
|
|
|
// 底部超出视口时向上调整 |
|
|
|
if (this.menuTop + menuHeight > window.innerHeight) { |
|
|
|
this.menuTop = window.innerHeight - menuHeight; |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 处理菜单操作 |
|
|
|
handleMenuAction(action) { |
|
|
|
console.log(`执行操作: ${action}`); |
|
|
|
// 这里可以添加具体的业务逻辑 |
|
|
|
this.hideMenu(); // 执行完操作后隐藏菜单 |
|
|
|
}, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
@ -219,23 +285,29 @@ export default { |
|
|
|
background-color: #fff; |
|
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |
|
|
|
border-radius: 12px 12px 0 0; |
|
|
|
position: relative; |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon { |
|
|
|
padding: 20px; |
|
|
|
float: left; |
|
|
|
width: 100%; |
|
|
|
min-height: 560px; |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon:first-child { |
|
|
|
margin-bottom: 22px; |
|
|
|
box-shadow: 1px 7px 10px 3px rgba(0, 0, 0, 0.1); |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon:nth-child(2) { |
|
|
|
margin-top: 22px; |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon:nth-child(2) .sflist { |
|
|
|
background-color: #f1ebeb; |
|
|
|
} |
|
|
|
|
|
|
|
.sfind { |
|
|
|
width: 100%; |
|
|
|
/* height: 40px; */ |
|
|
|
@ -243,6 +315,7 @@ export default { |
|
|
|
padding: 12px; |
|
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |
|
|
|
} |
|
|
|
|
|
|
|
.sfind .selbox { |
|
|
|
height: 40px; |
|
|
|
border-top: none; |
|
|
|
@ -252,6 +325,7 @@ export default { |
|
|
|
outline: none; |
|
|
|
padding: 0 12px; |
|
|
|
} |
|
|
|
|
|
|
|
.sfind .inputbox { |
|
|
|
height: 40px; |
|
|
|
line-height: 40px; |
|
|
|
@ -263,6 +337,7 @@ export default { |
|
|
|
outline: none; |
|
|
|
width: 460px; |
|
|
|
} |
|
|
|
|
|
|
|
.sfind button { |
|
|
|
width: 70px; |
|
|
|
height: 40px; |
|
|
|
@ -270,17 +345,20 @@ export default { |
|
|
|
background-color: #f5f5f5; |
|
|
|
border: none; |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon .sflist { |
|
|
|
min-height: 460px; |
|
|
|
overflow-y: auto; |
|
|
|
background-color: #f5f5f5; |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon .sflist ul { |
|
|
|
margin-top: 20px; |
|
|
|
display: block; |
|
|
|
width: 100%; |
|
|
|
min-height: 500px; |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon .sflist ul li { |
|
|
|
list-style: none; |
|
|
|
width: 100%; |
|
|
|
@ -290,6 +368,17 @@ export default { |
|
|
|
border-bottom: 1px dashed #ccc; |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon .sflist ul li:hover { |
|
|
|
background-color: #dad8d8; |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon .sflist ul li .sflfunc { |
|
|
|
/* display: none; */ |
|
|
|
float: right; |
|
|
|
width: 360px; |
|
|
|
margin-right: 20px; |
|
|
|
} |
|
|
|
|
|
|
|
.sfcon .sflist ul li .sfchkbox { |
|
|
|
margin-right: 12px; |
|
|
|
} |
|
|
|
@ -303,4 +392,40 @@ export default { |
|
|
|
float: left; |
|
|
|
margin-top: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
/* 传输功能区 */ |
|
|
|
.sftrans { |
|
|
|
position: fixed; |
|
|
|
width: 200px; |
|
|
|
height: 120px; |
|
|
|
z-index: 99; |
|
|
|
background-color: #f5f5f5; |
|
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |
|
|
|
} |
|
|
|
|
|
|
|
.sftrans .sfbcon { |
|
|
|
color: #333; |
|
|
|
margin-left: auto; |
|
|
|
margin-right: auto; |
|
|
|
background-color: #fff; |
|
|
|
padding:10px; |
|
|
|
} |
|
|
|
.sftrans .sfbcon li{ |
|
|
|
list-style: none; |
|
|
|
height: 30px; |
|
|
|
line-height: 30px; |
|
|
|
} |
|
|
|
.sftrans .sfbcon li:hover{ |
|
|
|
background-color: #00bd7e; |
|
|
|
color: #fff; |
|
|
|
cursor: default; |
|
|
|
} |
|
|
|
.sftrans .sfbcon li span{ |
|
|
|
padding-left: 12px; |
|
|
|
} |
|
|
|
.sftrans .sfbcon li.divider{ |
|
|
|
height: 1px; |
|
|
|
background-color: #00bd7e; |
|
|
|
margin: 10px 0; |
|
|
|
} |
|
|
|
</style> |