add tree.js
This commit is contained in:
parent
c8cc23b90e
commit
29f23d5594
|
@ -0,0 +1,115 @@
|
||||||
|
module.exports = { gen_tree_html }
|
||||||
|
|
||||||
|
function gen_tree_html (arr) {
|
||||||
|
const data = gen_tree_data(arr, is_gd_folder)
|
||||||
|
return tree_tpl(JSON.stringify(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
function tree_tpl (str) {
|
||||||
|
return `<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
|
||||||
|
<meta name="theme-color" content="#000000">
|
||||||
|
<title>Folder Tree</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/gh/iwestlin/gd-utils/static/tree.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- source code: https://github.com/iwestlin/foldertree/blob/master/app.jsx -->
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var treedata = ${str}
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/iwestlin/gd-utils/static/tree.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>`
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_gd_folder (data) {
|
||||||
|
return data.mimeType === 'application/vnd.google-apps.folder'
|
||||||
|
}
|
||||||
|
|
||||||
|
function gen_tree_data (data, is_folder) {
|
||||||
|
if (!data || !data.length) return []
|
||||||
|
const folders = data.filter(is_folder)
|
||||||
|
const files = data.filter(v => !is_folder(v))
|
||||||
|
const total_size = sum(files.map(v => v.size))
|
||||||
|
const root = {
|
||||||
|
title: `/根目錄 [共${files.length} 個檔案(不包括資料夾), ${format_size(total_size)}]`,
|
||||||
|
key: data[0].parent
|
||||||
|
}
|
||||||
|
if (!folders.length) return [root]
|
||||||
|
const sub_folders = folders.filter(v => v.parent === folders[0].parent)
|
||||||
|
sub_folders.forEach(v => {
|
||||||
|
sum_files(v, data, is_folder)
|
||||||
|
count_files(v, data, is_folder)
|
||||||
|
})
|
||||||
|
sort_folders(folders, 'count')
|
||||||
|
sort_folders(sub_folders, 'count')
|
||||||
|
folders.forEach(v => {
|
||||||
|
let {name, size, count, id} = v
|
||||||
|
if (name.length > 50) name = name.slice(0, 48) + '...'
|
||||||
|
v.title = `${name} | [共${count}個檔案 ${format_size(size)}]`
|
||||||
|
})
|
||||||
|
root.children = sub_folders.map(v => gen_node(v, folders))
|
||||||
|
return [root]
|
||||||
|
}
|
||||||
|
|
||||||
|
function sort_folders (folders, type) {
|
||||||
|
if (!folders || !folders.length) return
|
||||||
|
if (type === 'size') return folders.sort((a, b) => b.size - a.size)
|
||||||
|
if (type === 'count') return folders.sort((a, b) => b.count - a.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
function gen_node (v, folders) {
|
||||||
|
const {id, title, node} = v
|
||||||
|
if (node) return node
|
||||||
|
return v.node = {
|
||||||
|
title,
|
||||||
|
key: id,
|
||||||
|
children: v.children || folders.filter(vv => vv.parent === id).map(vv => gen_node(vv, folders))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function count_files (folder, arr, is_folder) {
|
||||||
|
if (folder.count) return folder.count
|
||||||
|
const children = arr.filter(v => v.parent === folder.id)
|
||||||
|
return folder.count = sum(children.map(v => {
|
||||||
|
if (is_folder(v)) return count_files(v, arr, is_folder)
|
||||||
|
return 1
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
function sum_files (folder, arr, is_folder) {
|
||||||
|
if (folder.size) return folder.size
|
||||||
|
const children = arr.filter(v => v.parent === folder.id)
|
||||||
|
return folder.size = sum(children.map(v => {
|
||||||
|
if (is_folder(v)) return sum_files(v, arr, is_folder)
|
||||||
|
return v.size
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
function sum (arr) {
|
||||||
|
let result = 0
|
||||||
|
for (const v of arr) {
|
||||||
|
result += Number(v) || 0
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
function format_size (n) {
|
||||||
|
n = Number(n)
|
||||||
|
if (Number.isNaN(n)) return ''
|
||||||
|
if (n < 0) return 'invalid size'
|
||||||
|
const units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||||
|
let flag = 0
|
||||||
|
while (n >= 1024) {
|
||||||
|
n = n / 1024
|
||||||
|
flag++
|
||||||
|
}
|
||||||
|
return n.toFixed(2) + ' ' + units[flag]
|
||||||
|
}
|
Loading…
Reference in New Issue