项目:webCommand | 版本:v1.0 | 生成日期:2026-10-05 | 依据:源码分析
webCommand(工程名 webcommand-nuxt,见 package.json 的 name 字段,版本 0.1.0)是一个极客风格的终端式浏览器主页:用户把浏览器新标签页指向本站点后,看到的是一个几乎全屏的黑底终端界面,所有功能都通过"敲命令"完成——baidu 关键词 打开百度搜索、todo add 写周报 添加待办、weather 北京 查天气、stock sh600519 查股票行情。它不是远程 Shell,也不会在服务器上执行任何系统命令;"终端"只是交互形态,命令的解释与执行全部发生在浏览器前端,只有少数需要绕过 CORS 或涉及账号数据的操作才会请求自家后端 API。
源码出处方面,README.md 明确声明本项目是衍生作品:主体交互与多数命令实现来自 YuIndex(作者 yupi,21 个文件带 @author yupi 署名,如 app/core/commands/gotoCommand.ts、app/components/shortcuts.ts),curl 命令移植自 m4tt72 的终端主页项目(app/core/commands/curl/curlCommand.ts 标注 @author m4tt72 (ported))。本仓库自研的部分包括:云同步合并语义与墓碑机制(app/composables/cloudMerge.ts)、运行期配置注入层(server/utils/appConfig.ts)、SQL 迁移器(server/utils/migrations.ts)、分级配额与账号准入(server/utils/dataAccess.ts、server/utils/accountPolicy.ts)、健康探活(server/api/health.get.ts)、双轨测试底座与部署脚本(test/、scripts/)。
目标用户可以归纳为三类:
help、Tab 补全、Ctrl+R 反向搜索历史等终端习惯完成日常动作;工程形态上是前后端合并单体:Nuxt 4 以 SPA 模式(nuxt.config.ts 中 ssr: false)承载前端,同一工程内的 server/ 目录由 Nitro 提供 REST API,生产环境以单个 Node 进程对外服务(静态资源 + /api 路由),数据库为 MySQL(Sequelize ORM)。
功能以"命令"为单位组织,命令清单唯一登记在 app/core/commandRegister.ts(数组顺序即 help 展示顺序),执行引擎在 app/core/commandExecutor.ts。按业务域归组如下:
| 功能域 | 命令(func) | 核心能力 | 是否需登录 | 实现位置(相对项目根) |
|---|---|---|---|---|
| 网页导航 | goto(别名 to/open/visit/jump/跳转) | 打开 URL,支持空间条目名解析、-s 当前页打开 | 否 | app/core/commands/gotoCommand.ts |
| 网页搜索 | search/baidu/google | 多引擎搜索,-f 选源、-c 当前页、-p 搜图片 | 否 | app/core/commands/search/*.ts |
| 待办事项 | todo add/list/delete/done/clear/stats | 任务增删改查与统计,登录后云同步 | 同步需登录 | app/core/commands/todo/ |
| 云端空间 | space 系(ls/add/mkdir/rm/pwd/cd/mv/cp) | 扁平 key-value 模拟的文件系统 + 收藏夹,提示符显示当前目录 | 同步需登录 | app/core/commands/space/ |
| 速记 | note add/list/rm/clear | 随手记一句话,登录后云同步 | 同步需登录 | app/core/commands/note/ |
| 自定义命令 | custom add/list/remove | 把常用命令文本映射为自定义名字(如 g => goto) | 同步需登录 | app/core/commands/custom/ |
| 账号体系 | user(login/register/logout/passwd/reset/delete) | 登录、注册、注销会话、改密、邮箱验证码找回密码、注销账号 | — | app/core/commands/user/ |
| 数据备份 | export/import | 导出 JSON 备份文件下载;粘贴 JSON 恢复 | 否 | app/core/commands/data/ |
| 信息查询 | weather/news/stock/ip/qrcode | 天气(wttr.in 代理)、热搜(三源容错)、A股行情(新浪)、公网 IP(四源容错)、二维码 | 否 | 各命令目录 + server/api/ 代理 |
| 开发小工具 | calc/convert/json/b64/uuid/ts/regex/color/varbook | 计算器、单位换算、JSON 格式化、Base64、UUID、时间戳、正则、取色器、变量命名助手 | 否 | `app/core/commands/calc |
| 终端本身 | clear/history/help/info/ping/date/timing/shortcut | 清屏、历史、帮助、站点信息、连通测试、日期、定时器、快捷键表 | 否 | app/core/commands/terminal/ 等 |
| 个性化 | background/theme/hint/welcome/reset | 终端背景(自定义 URL 或随机壁纸)、8 套配色主题、输入提示开关、欢迎语、配置重置 | 同步需登录 | app/core/commands/terminal/config/、theme/ |
| HTTP 工具 | curl | 浏览器端发起 GET 等 HTTP 请求并输出文本(受 CORS 限制) | 否 | app/core/commands/curl/curlCommand.ts |
除命令外,终端还内置了完整的交互基础设施:↑/↓ 翻阅历史、Ctrl+R 反向增量搜索、Ctrl+K 命令面板(模糊过滤全部命令与自定义命令)、Tab 循环补全命令名/子命令/选项、Ctrl+L 清屏、Ctrl+O 全部折叠/展开、输出快照刷新恢复、密码参数自动脱敏入历史等(见 app/components/shortcuts.ts、app/components/Terminal.vue、app/components/outputSnapshot.ts)。
| 层面 | 技术 | 版本(package.json 声明) | 选型理由(源自源码注释与结构推断) |
|---|---|---|---|
| 元框架 | Nuxt | ^4.5.2 | 单工程同时承载 SPA 前端(app/)与 Nitro 后端(server/),一套类型、一次部署 |
| 渲染模式 | SPA(ssr: false) | — | nuxt.config.ts 注释明示:终端型个人应用,数据来自 localStorage/登录态,无公开内容可收录;规避 localStorage 与 antd css-in-js 的水合成本;SPA 模式下 Nitro 后端依然完整可用 |
| UI 框架 | Vue | ^3.5.40 | 组合式 API + 全局 namespace 类型(Terminal.*) |
| 组件库 | ant-design-vue | ^4.2.6 | Collapse(折叠输出)、Input(命令输入框)、Tag(输出状态标)等;通过 unplugin-vue-components + AntDesignVueResolver 按需引入,css-in-js 模式,仅全局引 dist/reset.css |
| 状态管理 | pinia + @pinia/nuxt | ^4.0.3 / ^1.0.2 | 各业务域独立 store;pinia-plugin-persistedstate ^4.7.1 持久化到 localStorage |
| 认证 | nuxt-auth-utils | ^0.5.30 | 基于 cookie 的服务端 session(setUserSession/getUserSession/clearUserSession 全局函数),会话密钥 NUXT_SESSION_PASSWORD |
| ORM / 数据库 | sequelize ^6.37.8 + mysql2 ^3.24.2 | — | 两张表(user / user_data),模型懒加载单例;content 列 MEDIUMTEXT 存 JSON blob |
| HTTP 客户端(前端) | axios ^1.18.1 | — | app/utils/myAxios.ts 封装:baseURL 默认同源 /api,withCredentials,拦截器统一返回 {code,data,message} |
| 命令行参数解析 | getopts ^2.3.0 | — | app/core/commandExecutor.ts 用它把命令文本解析成位置参数与 -x/--xx 选项 |
| 邮件 | nodemailer ^6.10.1 | — | 找回密码验证码发送(server/thirdparty/mailer.ts) |
| 工具库 | lodash ^4.18.1、dayjs ^1.11.23 | — | hint.ts 用 debounce/trim;app/utils/myDayjs.ts 封装 dayjs |
| 测试 | node:test(原生)+ vitest ^2.1.9 + happy-dom | — | 双轨测试:test/*.spec.ts 用 node:test 跑纯函数与静态契约(零依赖、靠 Node ≥22.18 类型剥离);test/routes/** 用 vitest 路由层 |
| 代码质量 | ESLint ^10(@nuxt/eslint)+ Prettier ^3.9.6 + vue-tsc ^3.3.11 | — | ESLint 只管质量(关闭 stylistic),格式归 Prettier,避免双规则冲突;no-explicit-any 恢复为 error |
| 部署 | Docker + docker-compose | node:22-slim | 产物在宿主机构建(nuxt build),容器只负责运行 .output/server/index.mjs |
webCommand/
├── nuxt.config.ts # Nuxt 配置:ssr:false、模块注册、runtimeConfig(只放非敏感默认值)、SEO head
├── package.json # 脚本:dev/build/preview/lint/typecheck/test/test:routes/test:all
├── Dockerfile # node:22-slim 运行镜像(.output 宿主机构建后 COPY 进来,补装 mysql2)
├── docker-compose.yml # 真实编排(.gitignore 忽略,不入库)
├── docker-compose.example.yml# 编排模板:healthcheck、NUXT_* 环境变量占位
├── auth.d.ts # nuxt-auth-utils 会话 User 类型扩展(id/username/email)
├── vitest.config.ts # vitest 只收 test/routes/** 与 test/unit/**,装 Nitro 全局替身
├── app/ # ── 前端(SPA)──
│ ├── app.vue # 根组件,仅 <NuxtPage/>
│ ├── pages/index.vue # 唯一页面:全屏 Terminal,负责登录态恢复与云同步初始化
│ ├── spa-loading-template.html # SPA 加载外壳:noscript SEO/兜底内容
│ ├── components/
│ │ ├── Terminal.vue # 终端主组件:输出列表、输入框、状态栏、折叠、历史、快照恢复
│ │ ├── ContentOutput.vue # 单条输出渲染:文本(状态 Tag + 复制按钮 + smartText 链接化)或动态组件
│ │ ├── CommandPalette.vue# Ctrl+K 命令面板:内置命令 + 自定义命令模糊过滤
│ │ ├── shortcuts.ts # 全局快捷键注册(Ctrl+L/O/R/K、Tab、↑/↓ 等)
│ │ ├── history.ts # 历史命令上翻/下翻
│ │ ├── hint.ts # 输入提示(防抖 300ms)与 Tab 循环补全
│ │ ├── outputSnapshot.ts # 输出快照序列化清洗 + 命令文本密码脱敏
│ │ └── type.d.ts # 全局 namespace Terminal:OutputType/TerminalType 等
│ ├── core/
│ │ ├── command.d.ts # CommandType/CommandParamsType/CommandOptionType 契约
│ │ ├── commandRegister.ts# 命令清单(数组)→ commandMap(func+别名 → 命令)
│ │ ├── commandExecutor.ts# 执行引擎:解析、子命令递归、自定义命令回退、--help、必填参数校验
│ │ └── commands/<域>/ # 40+ 个命令模块;带 subCommands/ 的为父命令;含 6 个可同步 store
│ ├── composables/
│ │ ├── useCloudSync.ts # 云同步工厂:拉取→合并→上传,防抖 800ms,回环防护
│ │ ├── cloudSyncRegistry.ts # 六类同步数据唯一清单 + 惰性 store 加载器
│ │ └── cloudMerge.ts # 合并原语:逐条 LWW、墓碑(30 天保留)、配置整包较新者胜
│ ├── plugins/pinia-persistedstate.client.ts # 客户端注册持久化插件(防重复注册)
│ └── utils/ # myAxios(API 客户端)、smartText(转义+链接化)、error、myDayjs
├── server/ # ── 后端(Nitro)──
│ ├── api/ # REST 路由:user/*(8 个)、data(读/sync 写)、weather/news/stock/ip/qrcode、background/get/random、health
│ ├── models/ # Sequelize 模型:User(user 表)、UserData(user_data 表)
│ ├── services/ # userService(注册/登录/改密/注销等)、passwordReset(验证码)
│ ├── plugins/ # check-env(生产启动守卫)、migrate(启动迁移,失败不阻断)
│ ├── thirdparty/ # mailer(SMTP)、background(随机壁纸)
│ └── utils/ # response(bizHandler/BizError/ERROR_CODE)、rateLimit(内存限流)、appConfig(运行期配置解析)、db、dataAccess(云数据准入)、accountPolicy、migrations、appStatus、httpClient
├── scripts/ # check-all(质量门禁)、deploy(构建+凭据扫描+核验)、backup-db、init-test-db.*、smoke-cloud-sync
├── test/ # *.spec.ts(node:test 纯函数/契约)+ routes/*.test.ts(vitest 路由层)+ unit/
└── public/ # favicon、og-image、site.webmanifest(PWA)、robots、sitemap阅读建议:想理解"一条命令如何被执行",从 app/pages/index.vue → app/components/Terminal.vue 的 doSubmitCommand → app/core/commandExecutor.ts 这条线读起;想理解"登录与数据如何上云",从 app/core/commands/user/userCommands.ts → app/composables/cloudSyncRegistry.ts → app/composables/useCloudSync.ts 读起;想理解"服务端如何挡住非法请求",从 server/utils/response.ts、server/utils/rateLimit.ts、server/utils/dataAccess.ts 三个文件读起。
前置条件(README.md 明确要求):Node ≥ 22.18(跑测试需要原生类型剥离;22.12/22.15 会报 ERR_UNKNOWN_FILE_EXTENSION,24.21 已实测可用)、pnpm、一个可连接的 MySQL。
# 1. 准备环境变量(复制示例并填写 DB_*;本地库可直接 localhost/root)
cp .env.example .env
# 2. 安装依赖(postinstall 会自动执行 nuxt prepare)
pnpm install
# 3. 启动开发服务器(http://localhost:3000,前端与 /api 同源)
pnpm dev数据库表无需手工创建:Nitro 启动时 server/plugins/migrate.ts 会执行 server/utils/migrations.ts 中的幂等 DDL,建出 user、user_data 与水位表 schema_migrations。
常用质量命令(均来自 package.json 的 scripts):
pnpm lint # ESLint(代码质量)
pnpm typecheck # nuxt typecheck(vue-tsc 全量类型检查)
pnpm test # node --test test/*.spec.ts(纯函数 + 静态契约)
pnpm test:routes # vitest run(路由层)
pnpm test:all # 两套测试依次跑
./scripts/check-all.sh # 格式 → lint → 类型 → 两套测试,一条命令全跑真实数据库端到端冒烟(不碰生产库):./scripts/init-test-db.sh 生成 .env.test 与 scripts/init-test-db.sql,手工执行该 SQL 建库建账号后,./scripts/smoke-cloud-sync.sh 会在 3100 端口起 dev 服务对 webcommand_test 库跑 26 条断言,覆盖迁移建表、blob 逐字往返(含 4 字节 emoji)、跨用户隔离、白名单与尺寸上限、改密与注销闭环、限流 429。
上手验证路径:打开首页后输入 help 应看到命令总表;user register -u test -p 12345678 -e t@t.com 注册并自动登录;随后 todo add 学一下 help 里的命令、theme set Dracula 即可体验"本地持久化 + 登录后云同步"。
本目录共 7 篇文档:00 总览(本文)、01 系统架构(前后端分层与数据流)、02 页面设计(终端 UI 与状态管理)、03 接口设计(Nitro REST 契约与认证)、04 数据模型(MySQL 表与前端数据结构)、05 核心流程(命令执行/登录鉴权/云同步等端到端链路)、06 部署运行(本地开发、Docker、测试体系)。