1.说明
近期遇到一个浏览用户文件的需求,类似于访问百度网盘那样的列表,包含文件和文件夹,这个功能实现起来很简单,从服务器获取到的文件列表至少要有文件id、父级文件id、是否文件夹这三个字段
2.html设计
前端排版看你实际情况设计,我这里只简单展示文件夹和文件夹以及对应的图表就行,文件时间等其他信息也可以自行展示。我这里使用table标签展示文件列表,每一个文件都是一个tr,效果如下
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试</title>
<script src="http://cdn.staticfile.org/jquery/2.0.0/jquery.min.js"></script>
</head>
<style>
#explorerContainer {
width: 800px;
margin: 0 auto;
/* display: none; */
}
.fileIco {
width: 32px;
height: 32px;
}
.fileRow {
width: 550px;
border-bottom: 1px solid #a75318;
line-height: 50px;
align-items: center;
padding: 0 20px;
margin-left: 110px;
}
.fileRow span {
height: 32px;
line-height: 32px;
}
.fileRow span {
margin: 0 10px;
}
.fileRow span a {
color: #582a0a;
}
</style>
<body>
<div id="explorerContainer">
<table>
<tbody>
<tr>
<td>
<div class="fileRow">
<span><a href="" id="upperLevel">上一级...</a></span>
</div>
</td>
</tr>
<tr>
<td>
<div class="fileRow">
<img src="folder.png" alt="" class="fileIco">
<span><a href="">新建文件夹1</a></span>
</div>
</td>
</tr>
<tr>
<td>
<div class="fileRow">
<img src="folder.png" alt="" class="fileIco">
<span><a href="javascript:void(0);">新建文件夹2</a></span>
</div>
</td>
</tr>
<tr>
<td>
<div class="fileRow">
<img src="exe.png" alt="" class="fileIco">
<span><a href="">测试文件.exe</a></span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
3.展示文件列表
样式设置好之后,我们先试着展示固定的文件,文件保存在一个数组中,每一个文件都有文件id,我这里使用文件路径代替,只要是唯一的就行,所以这里的每一个文件对象都有path、parent_path、isdir这三个属性,分别表示文件路径、父级文件路径、是否文件夹
let upperLevelPath = ""
let files = [
{
"category": 6,
"fs_id": 934435682367559,
"isdir": 1,
"local_ctime": 1621308615,
"local_mtime": 1621308615,
"path": "/sharelink0-480654963977751/3dsmax/3dmax2022",
"parent_path": "/sharelink3073240792-480654963977751/3dsmax",
"server_ctime": 1621308615,
"server_filename": "3dmax2022",
"server_mtime": 1644238064,
"size": 0
},
{
"category": 5,
"fs_id": 517879331580918,
"isdir": 0,
"local_ctime": 1521869688,
"local_mtime": 1521869688,
"md5": "2a5f6be1bbc6d24fc172e887ed424604",
"path": "/sharelink3073240792-480654963977751/3dsmax/Autodesk_3ds_Max_2019_EFGJKPS_Win_64bit_001_003.sfx.exe",
"parent_path": "/sharelink3073240792-480654963977751/3dsmax",
"server_ctime": 1521869688,
"server_filename": "Autodesk_3ds_Max_2019_EFGJKPS_Win_64bit_001_003.sfx.exe",
"server_mtime": 1561784982,
"size": 2115408424
},
...
]
再写一个函数遍历files文件数组,拼凑DOM展示,不过要注意“上一级”按钮要特别处理,虽然它应该具有文件夹的功能,但是它是一个特殊的文件夹
let upperLevelPath = ""
function showFiles(tempList, parent_path) {
let tbody = $('<tbody><tr><td> <div class="fileRow"><span><a href="javascript:void(0);" path="' + upperLevelPath + '" id="upperLevel">上一级...</a></span></div></td></tr></tbody>')
for (var i = 0, len = tempList.length; i < len; i++) {
if (tempList[i].parent_path == parent_path) {
let img = $('<img alt="" class="fileIco">')
if (tempList[i].isdir == 1) {
img.attr("src", 'folder.png')
} else {
img.attr("src", "exe.png")
}
let span = $('<span><a href="javascript:void(0);" path="' + tempList[i].path + '" parent_path="' + tempList[i].parent_path + '" is_dir=' + tempList[i].isdir + ' fs_id=' + tempList[i].fs_id + ' >' + tempList[i].server_filename + '</a></span>')
let fileRowDiv = $('<div class="fileRow"></div>')
fileRowDiv.append(img)
fileRowDiv.append(span)
if (tempList[i].isdir == 0) {
fileRowDiv.append($('<div id="rlink_div_' + tempList[i].fs_id + '"></div>'))
}
tbody.append($('<tr><td>' + fileRowDiv[0].outerHTML + '</td></tr>'))
}
}
$('tbody').empty()
$('tbody').append(tbody)
}
showFiles(files, "/sharelink3073240792-480654963977751/3dsmax")
再来看一下效果
4.浏览文件
文件列表可以从服务器获取,获取之后调用showFiles()进行出来,但还不具备点击功能,比如说点击文件夹应该展示该文件夹里的文件。当点击进入某个文件夹的时候记录一下它的父级路径,保存到“上一级”按钮,当要返回上一级的时候就很方便了,但是,如果还要再上一级,这时候就没办法了,不过,只能获取子文件的上级然后在文件列表里找到父级的父级,不用担心上级文件夹为空,因为能连进两级,那父级不必不为空。当点击了文件或文件夹,如果在文件列表里找不到它的子集了,这时候可以发起从服务器获取的请求,当然,应该先判断一下是否已经存在文件列表了,如果已经存在就不需要再次发起请求。
所以监听点击文件的方法也很容易写出来
function monitorFileClick() {
$('.fileRow span a').click(function () {
let path = $(this).attr("path")
let id_ = $(this).attr("id")
if (id_ == "upperLevel") {
if (!upperLevelPath) {
lastPath = $(".fileRow span a").last().attr("parent_path")
console.log('lastPath:', lastPath)
if (!lastPath) {
alert("没有上一级了哦")
return
}
for (var i = files.length - 1; i >= 0; i--) {
if (files[i].path == lastPath && files[i].parent_path) {
upperLevelPath = files[i].parent_path
break
}
}
if (!upperLevelPath) {
alert("没有上一级了啦啦啦啦啦")
return
}
}
showFiles(files, upperLevelPath)
upperLevelPath = ""
} else {
if ($(this).attr('is_dir') == 1) {
let isIn = isInTempList(files, path)
if (!isIn) {
alert("点击了文件夹,发起请求")
}
if ($(this).attr("parent_path")) {
upperLevelPath = $(this).attr("parent_path")
}
showFiles(files, path)
} else {
console.log("这不是文件夹")
if ($(this).attr("isSuccess") == 1) {
return
}
alert("请求文件")
}
}
})
}
function isInTempList(tempList, path) {
console.log("isInTempList()", tempList.length, path)
for (var i = 0, len = tempList.length; i < len; i++) {
if (tempList[i].parent_path == path) {
return true
}
}
return false
}
什么时候调用这个方法呢?当然是展示完列表就调用
function showFiles(tempList, parent_path) {
...
$('tbody').empty()
$('tbody').append(tbody)
monitorFileClick()
}
5.完整代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试</title>
<script src="http://cdn.staticfile.org/jquery/2.0.0/jquery.min.js"></script>
</head>
<style>
#explorerContainer {
width: 800px;
margin: 0 auto;
/* display: none; */
}
.fileIco {
width: 32px;
height: 32px;
}
.fileRow {
width: 550px;
border-bottom: 1px solid #a75318;
line-height: 50px;
align-items: center;
padding: 0 20px;
margin-left: 110px;
}
.fileRow span {
height: 32px;
line-height: 32px;
}
.fileRow span {
margin: 0 10px;
}
.fileRow span a {
color: #582a0a;
}
</style>
<body>
<div id="explorerContainer">
<table>
<tbody>
<tr>
<td>
<div class="fileRow">
<span><a href="" id="upperLevel">上一级...</a></span>
</div>
</td>
</tr>
<tr>
<td>
<div class="fileRow">
<img src="folder.png" alt="" class="fileIco">
<span><a href="">新建文件夹1</a></span>
</div>
</td>
</tr>
<tr>
<td>
<div class="fileRow">
<img src="folder.png" alt="" class="fileIco">
<span><a href="javascript:void(0);">新建文件夹2</a></span>
</div>
</td>
</tr>
<tr>
<td>
<div class="fileRow">
<img src="exe.png" alt="" class="fileIco">
<span><a href="">测试文件.exe</a></span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
<script>
let upperLevelPath = ""
let files = [
{
"category": 6,
"fs_id": 934435682367559,
"isdir": 1,
"local_ctime": 1621308615,
"local_mtime": 1621308615,
"path": "/sharelink0-480654963977751/3dsmax/3dmax2022",
"parent_path": "/sharelink3073240792-480654963977751/3dsmax",
"server_ctime": 1621308615,
"server_filename": "3dmax2022",
"server_mtime": 1644238064,
"size": 0
},
{
"category": 5,
"fs_id": 830937815955136,
"isdir": 0,
"local_ctime": 1521869699,
"local_mtime": 1521869699,
"md5": "a79f60762a81dba8fd806233e9941900",
"path": "/sharelink3073240792-480654963977751/3dsmax/Autodesk_3ds_Max_2019_EFGJKPS_Win_64bit_003_003.sfx.exe",
"parent_path": "/sharelink3073240792-480654963977751/3dsmax",
"server_ctime": 1521869699,
"server_filename": "Autodesk_3ds_Max_2019_EFGJKPS_Win_64bit_003_003.sfx.exe",
"server_mtime": 1561784982,
"size": 450021000
},
{
"category": 5,
"fs_id": 92781334838182,
"isdir": 0,
"local_ctime": 1521869691,
"local_mtime": 1521869691,
"md5": "4de7ffe1ca87511b599aa60a0bce4a24",
"path": "/sharelink3073240792-480654963977751/3dsmax/Autodesk_3ds_Max_2019_EFGJKPS_Win_64bit_002_003.sfx.exe",
"parent_path": "/sharelink3073240792-480654963977751/3dsmax",
"server_ctime": 1521869691,
"server_filename": "Autodesk_3ds_Max_2019_EFGJKPS_Win_64bit_002_003.sfx.exe",
"server_mtime": 1561784982,
"size": 2115408424
},
{
"category": 5,
"fs_id": 517879331580918,
"isdir": 0,
"local_ctime": 1521869688,
"local_mtime": 1521869688,
"md5": "2a5f6be1bbc6d24fc172e887ed424604",
"path": "/sharelink3073240792-480654963977751/3dsmax/Autodesk_3ds_Max_2019_EFGJKPS_Win_64bit_001_003.sfx.exe",
"parent_path": "/sharelink3073240792-480654963977751/3dsmax",
"server_ctime": 1521869688,
"server_filename": "Autodesk_3ds_Max_2019_EFGJKPS_Win_64bit_001_003.sfx.exe",
"server_mtime": 1561784982,
"size": 2115408424
},
{
"category": 6,
"fs_id": 381680330545337,
"isdir": 0,
"local_ctime": 1561785049,
"local_mtime": 1561785036,
"md5": "9afb7d34ac26ead6b7435421c7bd5014",
"path": "/sharelink3073240792-480654963977751/3dsmax/3dsmax2019zhuceji.zip",
"parent_path": "/sharelink3073240792-480654963977751/3dsmax",
"server_ctime": 1561785049,
"server_filename": "3dsmax2019zhuceji.zip",
"server_mtime": 1561785049,
"size": 2044074
},
{
"category": 6,
"fs_id": 934435682367559,
"isdir": 1,
"local_ctime": 1621308615,
"local_mtime": 1621308615,
"path": "/sharelink0-480654963977751/3dsmax/test",
"parent_path": "/sharelink0-480654963977751/3dsmax/3dmax2022",
"server_ctime": 1621308615,
"server_filename": "test",
"server_mtime": 1644238064,
"size": 0
},
{
"category": 6,
"fs_id": 934435682367559,
"isdir": 1,
"local_ctime": 1621308615,
"local_mtime": 1621308615,
"path": "/sharelink0-480654963977751/3dsmax/3dmax2023",
"parent_path": "/sharelink3073240792-480654963977751/3dsmax",
"server_ctime": 1621308615,
"server_filename": "3dmax2023",
"server_mtime": 1644238064,
"size": 0
},
{
"category": 6,
"fs_id": 934435682367559,
"isdir": 0,
"local_ctime": 1621308615,
"local_mtime": 1621308615,
"path": "/sharelink0-480654963977751/3dsmax/3dmax2023/test",
"parent_path": "/sharelink0-480654963977751/3dsmax/3dmax2023",
"server_ctime": 1621308615,
"server_filename": "3dmax2023test",
"server_mtime": 1644238064,
"size": 0
},
]
function showFiles(tempList, parent_path) {
let tbody = $('<tbody><tr><td> <div class="fileRow"><span><a href="javascript:void(0);" path="' + upperLevelPath + '" id="upperLevel">上一级...</a></span></div></td></tr></tbody>')
for (var i = 0, len = tempList.length; i < len; i++) {
if (tempList[i].parent_path == parent_path) {
let img = $('<img alt="" class="fileIco">')
if (tempList[i].isdir == 1) {
img.attr("src", 'folder.png')
} else {
img.attr("src", "exe.png")
}
let span = $('<span><a href="javascript:void(0);" path="' + tempList[i].path + '" parent_path="' + tempList[i].parent_path + '" is_dir=' + tempList[i].isdir + ' fs_id=' + tempList[i].fs_id + ' >' + tempList[i].server_filename + '</a></span>')
let fileRowDiv = $('<div class="fileRow"></div>')
fileRowDiv.append(img)
fileRowDiv.append(span)
if (tempList[i].isdir == 0) {
fileRowDiv.append($('<div id="rlink_div_' + tempList[i].fs_id + '"></div>'))
}
tbody.append($('<tr><td>' + fileRowDiv[0].outerHTML + '</td></tr>'))
}
}
$('tbody').empty()
$('tbody').append(tbody)
monitorFileClick()
}
function isInTempList(tempList, path) {
console.log("isInTempList()", tempList.length, path)
for (var i = 0, len = tempList.length; i < len; i++) {
if (tempList[i].parent_path == path) {
return true
}
}
return false
}
showFiles(files, "/sharelink3073240792-480654963977751/3dsmax")
function monitorFileClick() {
$('.fileRow span a').click(function () {
let path = $(this).attr("path")
let id_ = $(this).attr("id")
if (id_ == "upperLevel") {
if (!upperLevelPath) {
lastPath = $(".fileRow span a").last().attr("parent_path")
console.log('lastPath:', lastPath)
if (!lastPath) {
alert("没有上一级了哦")
return
}
for (var i = files.length - 1; i >= 0; i--) {
if (files[i].path == lastPath && files[i].parent_path) {
upperLevelPath = files[i].parent_path
break
}
}
if (!upperLevelPath) {
alert("没有上一级了啦啦啦啦啦")
return
}
}
showFiles(files, upperLevelPath)
upperLevelPath = ""
} else {
if ($(this).attr('is_dir') == 1) {
let isIn = isInTempList(files, path)
if (!isIn) {
alert("点击了文件夹,发起请求")
}
if ($(this).attr("parent_path")) {
upperLevelPath = $(this).attr("parent_path")
}
showFiles(files, path)
} else {
console.log("这不是文件夹")
if ($(this).attr("isSuccess") == 1) {
return
}
alert("请求文件")
}
}
})
}
</script>
</html>