// // 文件管理 模块 // const LANG_T = antSword['language']['toastr']; const LANG = antSword['language']['filemanager']['files']; class Files { // 需要参数 // 1.cell: 左侧layout.cell对象 // 2.manager 主对象(index.jsx) constructor(cell, manager) { const self = this; cell.setText(` ${LANG['title']}`); // 创建toolbar const toolbar = cell.attachToolbar(); // 加载本地缓存书签栏 let bookmark = JSON.parse(manager.storage('bookmarks').get('{}')); // 重新加载书签 this.reloadToolbar = () => { let bookmark_opts = [{ id: 'bookmark_add', type: 'button', icon: 'plus-circle', text: LANG['bookmark']['add'], enabled: !bookmark[manager.path] }]; if (!$.isEmptyObject(bookmark)) { bookmark_opts.push({ type: 'separator' }); }; for (let _ in bookmark) { bookmark_opts.push({ id: 'bookmark_' + _, text: bookmark[_], icon: 'bookmark-o', type: 'button', enabled: manager.path !== _ }); } // 添加清除按钮 if (bookmark_opts.length > 2) { bookmark_opts.push({ type: 'separator' }); bookmark_opts.push({ id: 'bookmark_remove', icon: 'remove', text: LANG['bookmark']['del'], type: 'button', enabled: !!bookmark[manager.path] }); bookmark_opts.push({ id: 'bookmark_clear', icon: 'trash-o', text: LANG['bookmark']['clear'], type: 'button' }); }; toolbar.clearAll(); toolbar.loadStruct([ { id: 'new', type: 'buttonSelect', icon: 'plus-circle', text: LANG['toolbar']['new'], openAll: true, options: [ { id: 'new_folder', icon: 'folder-o', type: 'button', text: LANG['toolbar']['folder'] }, { id: 'new_file', icon: 'file-o', type: 'button', text: LANG['toolbar']['file'] }, { type: 'separator' }, { id: 'new_wget', icon: 'cloud-download', type: 'button', text: LANG['toolbar']['wget'] }, { id: 'new_upload', icon: 'cloud-upload', type: 'button', text: LANG['toolbar']['upload'] } ] }, { type: 'separator' }, { id: 'up', type: 'button', icon: 'arrow-up', text: LANG['toolbar']['up'] }, { type: 'separator' }, { id: 'refresh', type: 'button', icon: 'refresh', text: LANG['toolbar']['refresh'] }, { type: 'separator' }, { id: 'home', type: 'button', icon: 'home', text: LANG['toolbar']['home'] }, { type: 'separator' }, { id: 'bookmark', type: 'buttonSelect', icon: 'bookmark', text: LANG['toolbar']['bookmark'], openAll: true, options: bookmark_opts }, { type: 'separator' }, { id: 'path', width: 300, type: 'buttonInput', value: manager.path || 'loading..' }, { id: 'read_path', type: 'button', icon: 'arrow-right', text: LANG['toolbar']['read'] }, { type: 'separator' } ]); } this.reloadToolbar(); // reloadToolbar(); // this.reloadToolbar = reloadToolbar; // toolbar点击事件 toolbar.attachEvent('onClick', (id) => { switch(id) { case 'up': self.gotoPath('..'); break; case 'refresh': self.refreshPath(); break; case 'read_path': let pwd = toolbar.getInput('path').value; self.gotoPath(pwd); break; case 'home': self.gotoPath(manager.home); break; case 'new_folder': manager.createFolder(); break; case 'new_file': manager.createFile(); break; case 'new_wget': manager.wgetFile(); break; case 'new_upload': manager.uploadFile(); break; case 'bookmark_add': // 添加书签 layer.prompt({ value: self.manager.path, title: LANG['prompt']['add']['title'] }, (value, i, e) => { bookmark[self.manager.path] = value; self.manager.storage('bookmarks').set(JSON.stringify(bookmark)); toastr.success(LANG['prompt']['add']['success'](self.manager.path), LANG_T['success']); self.reloadToolbar(); layer.close(i); }); break; case 'bookmark_remove': layer.confirm( LANG['prompt']['remove']['confirm'] , { icon: 2, shift: 6, title: ` ${LANG['prompt']['remove']['title']}`, } , (_) => { // 删除书签并刷新 delete bookmark[self.manager.path]; self.manager.storage('bookmarks').set(JSON.stringify(bookmark)); self.reloadToolbar(); toastr.success(LANG['prompt']['remove']['success'], LANG_T['success']); layer.close(_); } ) break; case 'bookmark_clear': layer.confirm( LANG['prompt']['clear']['confirm'] , { icon: 2, shift: 6, title: ` ${LANG['prompt']['clear']['title']}` } , (_) => { bookmark = {}; self.manager.storage('bookmarks').set('{}'); self.reloadToolbar(); toastr.success(LANG['prompt']['clear']['success'], LANG_T['success']); layer.close(_); } ) break; default: let arr = id.split('_'); if (arr.length === 2 && arr[0] === 'bookmark') { self.gotoPath(arr[1]); }; } }); toolbar.attachEvent('onEnter', (id, value) => { switch(id) { case 'path': self.gotoPath(value); break; } }); // 创建grid let grid = cell.attachGrid(); grid.setHeader(`  , ${LANG['grid']['header']['name']}, ${LANG['grid']['header']['time']}, ${LANG['grid']['header']['size']}, ${LANG['grid']['header']['attr']} `); grid.setColTypes("ro,ro,ro,ro,ro"); grid.setColSorting('str,str,str,str,str'); grid.setInitWidths("40,*,150,100,100"); grid.setColAlign("center,left,left,right,center"); grid.enableMultiselect(true); // grid.enableDragAndDrop(true); // grid.enableMultiline(true); // grid右键 // 空白数据右键fix $('.objbox').on('contextmenu', (e) => { (e.target.nodeName === 'DIV' && grid.callEvent instanceof Function && antSword['tabbar'].getActiveTab().startsWith('tab_filemanager_')) ? grid.callEvent('onRightClick', [-1, -1, e]) : null; }); $('.objbox').on('click', (e) => { bmenu.hide(); }); grid.attachEvent('onRightClick', function(id, lid, event) { // 获取选中ID列表 let _ids = (this.getSelectedId() || '').split(','); // 如果是空白右键 if (id === -1) { _ids = []; } // 如果没有选中?则选中右键对应选项 else if (_ids.length === 1) { this.selectRowById(id); _ids = [id]; }; let ids = []; _ids.map((_) => { ids.push(this.getRowAttribute(_, 'fname')); }); id = ids[0] || ''; // 获取剪贴板内容 let _Clipboard = []; let _Clipboard_num = 0; for (let c in self.Clipboard) { _Clipboard.push({ text: antSword.noxss(c), icon: 'fa fa-' + (c.endsWith('/') ? 'folder-o' : 'file-o'), action: ( (source, name) => { return () => { manager.pasteFile(source, name); } })(self.Clipboard[c], c) }); _Clipboard_num ++; if (!(_Clipboard_num % 5)) { _Clipboard.push({ divider: true }); }; } // 清除最后的divider // if (_Clipboard.length % 5 && _Clipboard_num > 5) { _Clipboard.pop() }; // all item if (_Clipboard.length > 0) { _Clipboard.unshift({ divider: true }); _Clipboard.unshift({ text: LANG['grid']['contextmenu']['paste']['all'], count: _Clipboard_num, icon: 'fa fa-th-list', action: () => { _Clipboard.map( (c) => { if (c['divider'] || c['count'] || c['text'] === LANG['grid']['contextmenu']['paste']['clear']['title']) { return }; let name = c['text']; let source = self.Clipboard[name]; manager.pasteFile(source, name); } ); } }); // 清空剪贴板 !(_Clipboard[_Clipboard.length-1].divider) ? _Clipboard.push({ divider: true }) : 0; _Clipboard.push({ text: LANG['grid']['contextmenu']['paste']['clear']['title'], icon: 'fa fa-trash-o', action: () => { self.Clipboard = {}; toastr.info(LANG['grid']['contextmenu']['paste']['clear']['info'], LANG_T['info']); } }); }; let isFolder = id.endsWith('/'); // 可编辑文件后缀 let isEdited = false; 'php,asp,aspx,jsp,cfm,js,css,html,py,sh,bat,txt,log,ini,conf,sql'.split(',').map( (e) => { id.toLowerCase().endsWith(`.${e}`) ? isEdited = true : 0; } ); let menu = [ { text: LANG['grid']['contextmenu']['refresh'], icon: 'fa fa-refresh', action: () => { self.refreshPath(); } }, { divider: true }, { text: LANG['grid']['contextmenu']['wget'], icon: 'fa fa-cloud-download', action: manager.wgetFile.bind(manager) }, { text: LANG['grid']['contextmenu']['upload'], icon: 'fa fa-upload', action: manager.uploadFile.bind(manager) }, { text: LANG['grid']['contextmenu']['download'], icon: 'fa fa-download', disabled: isFolder || !id || ids.length > 1, action: () => { manager.downloadFile(id, this.getRowAttribute(_ids[0], 'fsize')); } }, { divider: true }, { text: LANG['grid']['contextmenu']['copy']['title'], icon: 'fa fa-copy', disabled: !id, action: () => { // 如果只有一个id,则显示id名称,否则显示ids数量 ids.map( (id) => { let path = manager.path + id; // 判断是否已经复制 if (id in self.Clipboard) { return toastr.warning(LANG['grid']['contextmenu']['copy']['warning'](id), LANG_T['warning']); }; self.Clipboard[id] = path; toastr.info(LANG['grid']['contextmenu']['copy']['info'](id), LANG_T['info']); } ); } }, { text: LANG['grid']['contextmenu']['paste']['title'], icon: 'fa fa-paste', disabled: _Clipboard_num === 0, subMenu: _Clipboard }, { text: LANG['grid']['contextmenu']['preview'], icon: 'fa fa-eye', disabled: !id || ids.length > 1 || !self.checkPreview(id), action: () => { manager.previewFile(id, this.getRowAttribute(_ids[0], 'fsize')); } }, { divider: true }, { text: LANG['grid']['contextmenu']['edit'], icon: 'fa fa-edit', disabled: /*!isEdited || */!id || ids.length > 1 || isFolder, action: () => { manager.editFile(id); } }, { text: LANG['grid']['contextmenu']['delete'], icon: 'fa fa-trash-o', disabled: !id, action: () => { manager.deleteFile(ids); } }, { text: LANG['grid']['contextmenu']['rename'], icon: 'fa fa-font', disabled: !id || ids.length > 1, action: () => { manager.renameFile(id); } }, { text: LANG['grid']['contextmenu']['modify'], icon: 'fa fa-clock-o', disabled: !id || ids.length > 1, action: () => { // manager.retimeFile(id, this.rowsAr[id]['cells'][2].innerText); manager.retimeFile(id, this.getRowAttribute(_ids[0], 'data')[2]); } }, { divider: true }, { text: LANG['grid']['contextmenu']['create']['title'], icon: 'fa fa-plus-circle', subMenu: [ { text: LANG['grid']['contextmenu']['create']['folder'], icon: 'fa fa-folder-o', action: manager.createFolder.bind(manager) }, { text: LANG['grid']['contextmenu']['create']['file'], icon: 'fa fa-file-o', action: manager.createFile.bind(manager) } ] } ]; bmenu(menu, event); return true; }); // 选择事件 grid.attachEvent('onRowSelect', (id, lid, event) => { bmenu.hide(); }); // 双击文件 // :如果可预览并且小于 1MB,则进行预览 // :如果size < 100kb,则进行编辑,否则进行下载 grid.attachEvent('onRowDblClicked', (id, lid, event) => { const fname = grid.getRowAttribute(id, 'fname'); const fsize = grid.getRowAttribute(id, 'fsize'); if (!fname.endsWith('/')) { if(self.checkPreview(fname) && fsize <= 1000 * 1024){ manager.previewFile(fname, fsize); }else if(fsize <= 100 * 1024){ // 双击编辑size < 100kb 文件 manager.editFile(fname); }else{ manager.downloadFile(fname, fsize); } }else{ self.gotoPath(fname); } }); // 键盘按下事件 grid.attachEvent('onKeyPress', (code, cFlag, sFlag)=>{ switch (true){ case (code <= 90 && code >= 65)||(code<=57 && code >= 48): // A-Z 0-9 var input = String.fromCharCode(code); input = input.toLowerCase(); var sid = 0; var ids = grid.getAllRowIds().split(","); for (var i=0; i= ids.length-1 ? parseInt(ids[ids.length-1])-1 : parseInt(ids[ids.indexOf(sid) + 1])-1; grid.selectRow(cid); break; default: break; } }); grid.init(); this.grid = grid; this.cell = cell; this.toolbar = toolbar; this.manager = manager; // 剪贴板 this.Clipboard = {}; // 文件拖拽上传 $(this.cell.cell).on({ dragleave: (e) => { e.preventDefault() }, drop: (e) => { e.preventDefault(); let filePaths = []; let files = e.originalEvent['dataTransfer']['files'] || {}; for (let i = 0; i < files.length; i++) { let f = files.item(i); filePaths.push(f['path']); } this.manager.uploadFile(filePaths); }, dragenter: (e) => { e.preventDefault() }, dragover: (e) => { e.preventDefault() } }); } checkPreview(name) { // 可预览文件后缀 let isPreviewed = false; 'jpeg,jpg,png,gif,bmp,ico'.split(',').map( (e) => { name.toLowerCase().endsWith(`.${e}`) ? isPreviewed = true : 0; } ); return isPreviewed; } // 刷新当前目录 // 如果传递路径参数,则刷新该路径下的文件,不跳转,否则刷新&&跳转 refreshPath(p) { let path = p || this.manager.path; // delete this.manager.cache[path]; this.manager.cache.del('filemanager-files-' + new Buffer(path).toString('base64')); // 删除文件夹缓存 for (let _ in this.manager.folder.cache) { if (_.indexOf(path) === 0 && _ != path) { delete this.manager.folder.cache[_]; } } if (!p) { this.gotoPath('.') }; } // 跳转目录 gotoPath(path) { let self = this; this.cell.progressOn(); try{ this.manager.getFiles(path, (files) => { self.parse(files); self.manager.folder.parse(files); // self.cell.progressOff(); }); }catch(e) { toastr.error(e, LANG_T['error']); self.cell.progressOff(); } } // 解析数据 parse(files) { let data = []; let self = this; let _id = 1; files.map( (file) => { if (!file['name'] || ['./', '../'].indexOf(file['name']) != -1) {return}; data.push({ id: _id, fname: file['name'], fsize: parseInt(file['size']), // 如果是可执行文件(exe、dll..),则设置为红色字体 style: /\.exe$|\.dll$|\.bat$|\.sh$|\.com$/.test(file['name']) ? 'color:red' : '', data: [ self.fileIcon(file['name']), antSword.noxss(file['name'].replace(/\/$/, '')), antSword.noxss(file['time']), antSword.noxss(self.fileSize(parseInt(file['size']))), antSword.noxss(file['attr']) ] }); _id ++; } ); this.cell.setText(` ${LANG['title']} (${data.length})`); this.grid.clearAll(); this.grid.parse({ 'rows': data }, 'json'); // 设置path路径 this.toolbar.getInput('path').value = this.manager.path; this.cell.progressOff(); this.reloadToolbar(); } // 文件大小计算 fileSize(t) { let i = false; let b = ["b","Kb","Mb","Gb","Tb","Pb","Eb"]; for (let q=0; q 1024) t = t / 1024; else if (i === false) i = q; if (i === false) i = b.length-1; return Math.round(t*100)/100+" "+b[i]; } // 返回文件图标 fileIcon(name) { let icons = {}; const _icons = { 'exe,dll': 'file', 'jpg,png,gif,ico,bmp': 'file-image-o', 'mp4,mpeg,avi,rm,rmvb': 'file-movie-o', 'mp3,mid,wav': 'file-sound-o', 'pdf': 'file-pdf-o', 'ppt': 'file-powerpoint-o', 'xls,xlsx': 'file-excel-o', 'doc,docx': 'file-word-o', 'zip,tar,7z,gz,rar': 'file-archive-o', 'txt,ttf,tiff,ini,log,chm,conf,cfg': 'file-text-o', 'php,asp,jsp,sql,cfm,aspx,html,js,py,rb,pl,go,css,less,jsx,sass,xml,sh,bat,h,cpp,c,m': 'file-code-o' } for (let _ in _icons) { let _arr = _.split(','); _arr.map( (a) => { icons[a] = _icons[_]; }); } // 默认图标 let icon = 'file-o'; // 判断是否为文件夹 if (name.endsWith('/')) { icon = 'folder-o'; }else{ let _ = name.split('.'); let ext = _[_.length - 1].toLowerCase(); icon = icons[ext] || icon; }; return ``; } } // export default Files; module.exports = Files;