项目概述:利用暑假的时间在知识星球学习鱼皮的 web 终端项目,这是一个通过命令行的方式在浏览器运行的一个工具库
项目亮点:
- 避免反复跳转网页,功能全部集成到命令集中,通过像 Linux 一样终端输入输出的方式,更加炫酷
- 网上前端开发比较缺少这种偏逻辑的项目,可以很好的锻炼自己的技术栈
- 考虑到系统较复杂,自主设计 web 微终端、命令系统以及命令集 3 个子系统
- 做这种东西自己会更有兴趣和动力
开源地址:web-terminal
命令手册:command lsit
// 1. 进入server目录,安装依赖
yarn
// 2. 配置mysql数据库
文件地址:/server/db/ddl.sql
// 3. 配置Redis,具体可查看网上的教程
// 4. 运行后台
yarn run start:dev
//安装前台依赖
yarn
//运行前台服务
yarn run dev
:::info
- 这个功能有没有是否影响你项目的上线?(只要不影响,都先不做)
- 功能的实用性、是否贴合主题 :::
- 终端完成简单的输入输出
- 对输入的指令进行解析
- 渲染解析的结果异步加载到 Vue 组件
- 项目的通用性设计(系统设计,定制规范)
- 开发多种适配命令
:::info 在有限的条件和特点场景下下,寻求技术最优解 :::
- 不要重复造轮子,尽早做技术选型
- 从系统的大类细分,需要前端/后端/客户端/......,大的方向再细分技术
- 要从实际出发,贴合业务和项目。比如老项目要考虑版本兼容性,新项目结合实际需求和现有资源
- 业务量级、核心流程和关键数据、性能偏向哪些方面
- 从自己/团队现有的技术栈考虑,不要引入冷门的技术
主要技术:
- Node.js后台
- Express、express-session
- MySQL
- Sequelize(ORM 框架)
- Redis
依赖库:
- Axios
- 网易云音乐 NeteaseCloudMusicApi
- 百度翻译 API
主要技术:
- Vue 3 前端开发,主流
- Vite 2 前端构建工具,新兴 / 优秀,本地编译速度很快,提高开发效率
- Ant Design Vue 3 组件库(不用 Element UI?用的熟练,ant design 主流,支持 vue 和 react,更通用)
- Pinia 2 状态管理(Vuex,pinia 兼容 vuex)
- TypeScript 类型控制(项目规范,编辑器 / 开发工具会给你提示问题)
- Eslint 代码规范控制(项目规范,自动语法校验)
- Prettier 美化代码(项目规范,自动格式化代码)
依赖库:
- axios 网络请求
- dayjs 时间处理
- lodash 工具库
- getopts 命令参数解析
系统主要分为以下三个模块:
- 微终端:系统显示的主界面
- 命令系统:接受匹配的命令,解析执行
- 命令集:用户定义的命令集规则
- 接受用户的输入,控制用户的输出
- 用户输入使用防抖匹配命令集的命令,匹配到在底部显示
- 用户执行的命令会存储到列表中,方便历史命令接口查询
- 快捷键如清空屏幕、上下键
- 操作接口主要是暴露给命令系统的方法,规定可以对终端做哪些操作
const onSubmitCommand = async (inputText: string) => {
if (!inputText) {
return;
}
const terminal = terminalRef.value.terminal;
console.log("1 接受终端输入", inputText, terminal);
await doCommandExecute(inputText, terminal);
};
- 将终端封装成一个组件的形式,外部进行调用
- 外部接受到组件的输入,然后才调用命令系统(分离逻辑,扩展更加容易)
- 用户输入使用 watchEffect 追踪,调用 hint.ts 方法
- 使用前缀匹配命令集 map 中第一个命令,返回值,临时渲染到输入框下方
const commandList = ref<CommandOutputType[]>([]);
- 使用数组列表存储过往数据
- 控制索引,可以根据上下键、list命令查看历史命令
export const registerShortcuts = (terminal: TerminalType) => {
document.onkeydown = (e) => {
// console.log(e);
let key = e.key;
// 自动聚焦输入框
if (key >= "a" && key <= "z" && !e.metaKey && !e.shiftKey && !e.ctrlKey) {
terminal.focusInput();
return;
}
// 匹配快捷键
let code = e.code;
for (const shortcut of shortcutList) {
if (
code === shortcut.code &&
e.ctrlKey == !!shortcut.ctrlKey &&
e.metaKey == !!shortcut.metaKey &&
e.shiftKey == !!shortcut.shiftKey
) {
shortcut.action(e, terminal);
}
}
};
};
- 全局监听用户键盘输入,并且匹配对应的方法
/**
* 操作终端的对象
*/
const terminal: TerminalType = {
writeTextResult,
writeTextErrorResult,
writeTextSuccessResult,
writeResult,
writeTextOutput,
writeOutput,
clear,
focusInput,
isInputFocused,
setTabCompletion,
doSubmitCommand,
showNextCommand,
showPrevCommand,
listCommandHistory,
toggleAllCollapse,
setCommandCollapsible,
};
- 微终端可以暴露给外部的操作接口
- 防止未按照规定方式操作屏幕
- 采用匹配 => 解析 => 执行机制实现
- 子命令通过递归的方式实现子命令解析
const getCommand = (text: string, parentCommand?: CommandType): CommandType => {
let func = text.split(" ", 1)[0];
console.log("3 解析开头命令", func);
// 大小写无关
func = func.toLowerCase();
let commands = commandMap;
// 有父命令,则从父命令中查找
if (
parentCommand &&
parentCommand.subCommands &&
Object.keys(parentCommand.subCommands).length > 0
) {
commands = parentCommand.subCommands;
}
const command = commands[func];
console.log("3 匹配命令,到map命令集搜索", command);
return command;
};
- 首次获取传入的text文本,分割首位命令
- 如果有子命令,递归调用函数判断
命令行解析工具: GitHub - jorgebucaran/getopts: Node.js CLI options parser
/**
* 命令类型
*/
interface CommandType {
// 命令英文 key(必须唯一)
func: string;
// 命令名称
name: string;
// 介绍
desc?: string;
// 功能别名
alias?: string[];
// 参数配置
params?: CommandParamsType[];
// 选项配置
options: CommandOptionType[];
// 子命令
subCommands?: Record<string, CommandType>;
// 执行功能
action: (
options: ParsedOptions,
terminal: TerminalType,
parentCommand?: CommandType
) => void;
// 结果是否允许折叠
collapsible?: boolean;
}
- 调用命令action的方法
- 将结果展示到终端上面
- 以单文件分离的方法管理命令集
- 统一规范命令集
- 使用 Map :key - value 存储结果,避免循环搜索
:::info 需要进行前后端交互,即获取数据的接口如下 :::
- 用户模块:user
- 翻译模块:fanyi
- 背景图片:bg
- 音乐模块:music
- 增加更多的命令
- 开发后台管理系统,开发者上传代码到后台审核,前端用户安装命令包
- 解决性能优化
- 适配移动端、桌面端开发
- 接入gpt形成对话功能模块
- 开发和用户交互的小游戏,比如猜拳......
- 私有化存储收藏夹,分类查询修改
- 优化数据存储,目前数据大部分存储在浏览器,后续可以把一些数据量大的过渡到 MySQL 数据库
- 利用暑假的时间在知识星球学习鱼皮的 web 终端项目,学到了很多知识
- 了解了一个项目从0到1的技术选型,要考虑哪些功能,技术栈如何选择
- 简单学习了 Redis 的知识点,重温了express后台的知识点
- 如何更好的分离代码组件设计,做到高内聚,低耦合
- 学习了如何通过 ESLint + Prettier + TypeScript 更好的约束代码开发,学习了前端代码工程化
- 开发一个获取头像的接口命令
- 用户登录修改为 linux 模式
- 完善 todo 命令
- 扩展后台,目前只有调用翻译、音乐接口、用户登录功能
- 接入 gpt 进行聊天
lodash前端工具库 Lodash 前端必备神器:学会这些技巧,让你代码量减半、效率翻倍! - 掘金
pinia如何使用持久化 Pinia的使用以及数据持久化 - 掘金
组件库
Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js