diff --git a/assets/html/404.html b/assets/html/404.html new file mode 100644 index 0000000..c9f519d --- /dev/null +++ b/assets/html/404.html @@ -0,0 +1,425 @@ + + + + + + 404 - 页面未找到 | Page Not Found + + + +
+ + + + +
+
🔍
+ +
+ 很抱歉,无法找到您要访问的页面。
+ 这可能是因为页面已被删除、移动或者您输入的网址有误。 +
+ +
+

您可以尝试以下操作

+
    +
  • 检查网址是否输入正确
  • +
  • 返回上一页继续浏览
  • +
  • 访问网站首页
  • +
  • 使用搜索功能查找内容
  • +
  • 联系网站管理员报告此问题
  • +
+
+ + +
+ + +
+ + + + diff --git a/commands/http.js b/commands/http.js index 105df1c..335230d 100644 --- a/commands/http.js +++ b/commands/http.js @@ -2,17 +2,20 @@ const fs = require('fs'); const { Command, printer } = require('@axiosleo/cli-tool'); -const { error, Router, KoaApplication, result } = require('../'); +const { Router, KoaApplication, result } = require('../'); const path = require('path'); const promisify = require('util').promisify; const readdir = promisify(fs.readdir); +const stat = promisify(fs.stat); const { _exists, _is_file, _is_dir, _ext } = require('@axiosleo/cli-tool/src/helper/fs'); -const { _fixed } = require('@axiosleo/cli-tool/src/helper/str'); +const { + _fixed +} = require('@axiosleo/cli-tool/src/helper/str'); const mimeTypes = { 'css': 'text/css', @@ -43,6 +46,36 @@ class HttpCommand extends Command { }); this.addArgument('dir', 'Static directory', 'optional', process.cwd()); this.addOption('port', 'p', 'Port', 'optional', 80); + this.html404Content = null; + } + + formatFileSize(bytes) { + if (bytes === 0) { return '--'; } + const k = 1024; + const sizes = ['B', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; + } + + getFileType(filename, is_dir, ext) { + if (is_dir) { return 'folder'; } + + const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp']; + const codeExts = ['js', 'ts', 'html', 'css', 'json', 'xml', 'sh', 'py', 'java', 'cpp', 'c', 'php']; + + if (imageExts.includes(ext.toLowerCase())) { return 'image'; } + if (codeExts.includes(ext.toLowerCase())) { return 'code'; } + return 'document'; + } + + getFileIcon(type) { + const icons = { + folder: '📁', + document: '📄', + image: '🖼️', + code: '💻' + }; + return icons[type] || '📄'; } async list(dir) { @@ -57,8 +90,21 @@ class HttpCommand extends Command { await Promise.all(tmp.map(async (filename) => { let filepath = path.join(dir, filename); let is_dir = await _is_dir(filepath); - files.push({ filename, is_dir, filepath }); + let stats = await stat(filepath); + let size = is_dir ? 0 : stats.size; + let mtime = stats.mtime; + let ext = is_dir ? '' : _ext(filename); + + files.push({ + filename, + is_dir, + filepath, + size, + mtime, + ext + }); })); + // debug.log(files); return files; } @@ -75,7 +121,43 @@ class HttpCommand extends Command { let d = path.join(dir, url.pathname); printer.yellow(_fixed('[' + context.method + ']', 12, 'r')).green(context.url).println(); if (!await _exists(d)) { - error(404, 'Not Found'); + if (!this.html404Content) { + // 读取 404.html 文件内容 + const html404Path = path.join(__dirname, '../assets/html/404.html'); + let html404Content = 'Not Found'; + try { + html404Content = fs.readFileSync(html404Path, 'utf8'); + } catch (_error) { // eslint-disable-line no-unused-vars + // 如果读取失败,使用简单的 HTML 404 页面 + html404Content = ` + + + + + 404 - 页面未找到 + + + +
+

404

+

页面未找到

+

抱歉,您访问的页面不存在或已被移动。

+ 返回首页 +
+ +`; + } + this.html404Content = html404Content; + } + + result(this.html404Content, 404, { 'Content-Type': 'text/html' }); } if (await _is_file(d)) { const extname = _ext(d); @@ -91,17 +173,397 @@ class HttpCommand extends Command { context.koa.body = stream; return; } - let htmlContent = ''; + + const htmlContent = ` + + + + + 文件列表 - File List + + + +
+
+

📁 文件管理器

+

File Manager

+
+ + + +
+ + +
+ ${fileItemsHTML} +
+
+ +
+
+ ${folderCount} +
文件夹
+
+
+ ${fileCount} +
文件
+
+
+ ${this.formatFileSize(totalSize)} +
总大小
+
+
+
+ + + +`; + + // debug.log('Generated HTML file listing'); result(htmlContent, 200, { 'Content-Type': 'text/html' }); }], });