feat: 初始化前后端Node.js控制台项目基础架构
- 创建项目核心文件:package.json、vite.config.js、.gitignore - 添加前后端基础依赖和开发工具配置 - 完善OpenSpec模块,包括项目文档和核心能力规格 - 配置ESLint和Prettier代码规范 - 创建基本目录结构 - 实现前端Vue3应用框架和路由 - 添加后端Express服务器和基础路由 - 编写README项目说明文档
This commit is contained in:
40
.eslintrc.js
Normal file
40
.eslintrc.js
Normal file
@@ -0,0 +1,40 @@
|
||||
export default {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/vue3-recommended'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: [
|
||||
'vue'
|
||||
],
|
||||
rules: {
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/no-unused-vars': 'warn',
|
||||
'vue/no-unused-components': 'warn',
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
|
||||
'indent': ['error', 2],
|
||||
'quotes': ['error', 'single'],
|
||||
'semi': ['error', 'always'],
|
||||
'no-trailing-spaces': 'error',
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
'array-bracket-spacing': ['error', 'always']
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.vue'],
|
||||
rules: {
|
||||
'indent': 'off'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
22
.github/prompts/openspec-apply.prompt.md
vendored
Normal file
22
.github/prompts/openspec-apply.prompt.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
description: Implement an approved OpenSpec change and keep tasks in sync.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
<!-- OPENSPEC:START -->
|
||||
**Guardrails**
|
||||
- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
|
||||
- Keep changes tightly scoped to the requested outcome.
|
||||
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
|
||||
|
||||
**Steps**
|
||||
Track these steps as TODOs and complete them one by one.
|
||||
1. Read `changes/<id>/proposal.md`, `design.md` (if present), and `tasks.md` to confirm scope and acceptance criteria.
|
||||
2. Work through tasks sequentially, keeping edits minimal and focused on the requested change.
|
||||
3. Confirm completion before updating statuses—make sure every item in `tasks.md` is finished.
|
||||
4. Update the checklist after all work is done so each task is marked `- [x]` and reflects reality.
|
||||
5. Reference `openspec list` or `openspec show <item>` when additional context is required.
|
||||
|
||||
**Reference**
|
||||
- Use `openspec show <id> --json --deltas-only` if you need additional context from the proposal while implementing.
|
||||
<!-- OPENSPEC:END -->
|
||||
26
.github/prompts/openspec-archive.prompt.md
vendored
Normal file
26
.github/prompts/openspec-archive.prompt.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: Archive a deployed OpenSpec change and update specs.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
<!-- OPENSPEC:START -->
|
||||
**Guardrails**
|
||||
- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
|
||||
- Keep changes tightly scoped to the requested outcome.
|
||||
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
|
||||
|
||||
**Steps**
|
||||
1. Determine the change ID to archive:
|
||||
- If this prompt already includes a specific change ID (for example inside a `<ChangeId>` block populated by slash-command arguments), use that value after trimming whitespace.
|
||||
- If the conversation references a change loosely (for example by title or summary), run `openspec list` to surface likely IDs, share the relevant candidates, and confirm which one the user intends.
|
||||
- Otherwise, review the conversation, run `openspec list`, and ask the user which change to archive; wait for a confirmed change ID before proceeding.
|
||||
- If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet.
|
||||
2. Validate the change ID by running `openspec list` (or `openspec show <id>`) and stop if the change is missing, already archived, or otherwise not ready to archive.
|
||||
3. Run `openspec archive <id> --yes` so the CLI moves the change and applies spec updates without prompts (use `--skip-specs` only for tooling-only work).
|
||||
4. Review the command output to confirm the target specs were updated and the change landed in `changes/archive/`.
|
||||
5. Validate with `openspec validate --strict` and inspect with `openspec show <id>` if anything looks off.
|
||||
|
||||
**Reference**
|
||||
- Use `openspec list` to confirm change IDs before archiving.
|
||||
- Inspect refreshed specs with `openspec list --specs` and address any validation issues before handing off.
|
||||
<!-- OPENSPEC:END -->
|
||||
27
.github/prompts/openspec-proposal.prompt.md
vendored
Normal file
27
.github/prompts/openspec-proposal.prompt.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
description: Scaffold a new OpenSpec change and validate strictly.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
<!-- OPENSPEC:START -->
|
||||
**Guardrails**
|
||||
- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
|
||||
- Keep changes tightly scoped to the requested outcome.
|
||||
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
|
||||
- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
|
||||
- Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.
|
||||
|
||||
**Steps**
|
||||
1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification.
|
||||
2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, and `design.md` (when needed) under `openspec/changes/<id>/`.
|
||||
3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing.
|
||||
4. Capture architectural reasoning in `design.md` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs.
|
||||
5. Draft spec deltas in `changes/<id>/specs/<capability>/spec.md` (one folder per capability) using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement and cross-reference related capabilities when relevant.
|
||||
6. Draft `tasks.md` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work.
|
||||
7. Validate with `openspec validate <id> --strict` and resolve every issue before sharing the proposal.
|
||||
|
||||
**Reference**
|
||||
- Use `openspec show <id> --json --deltas-only` or `openspec show <spec> --type spec` to inspect details when validation fails.
|
||||
- Search existing requirements with `rg -n "Requirement:|Scenario:" openspec/specs` before writing new ones.
|
||||
- Explore the codebase with `rg <keyword>`, `ls`, or direct file reads so proposals align with current implementation realities.
|
||||
<!-- OPENSPEC:END -->
|
||||
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Build outputs
|
||||
dist/
|
||||
dist-ssr/
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Testing
|
||||
coverage/
|
||||
*.lcov
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.temp
|
||||
10
.prettierrc
Normal file
10
.prettierrc
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "always",
|
||||
"htmlWhitespaceSensitivity": "ignore",
|
||||
"vueIndentScriptAndStyle": false
|
||||
}
|
||||
129
.trae/documents/完善前后端Node.js控制台项目的基础架构.md
Normal file
129
.trae/documents/完善前后端Node.js控制台项目的基础架构.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# 完善前后端Node.js控制台项目的基础架构
|
||||
|
||||
## 1. 项目初始化
|
||||
|
||||
### 1.1 创建核心配置文件
|
||||
- **package.json**: 初始化项目配置,包含项目基本信息、依赖管理、脚本命令等
|
||||
- **vite.config.js**: 配置Vite打包工具,支持前后端分离开发
|
||||
- **.gitignore**: 配置Git忽略文件,避免提交不必要的文件
|
||||
|
||||
### 1.2 安装核心依赖
|
||||
- **前端依赖**: Vue 3.x、Vue Router、Axios等
|
||||
- **后端依赖**: Express、Redis客户端、Cors等
|
||||
- **开发依赖**: Vite、ESLint、Prettier等
|
||||
|
||||
## 2. 完善OpenSpec模块
|
||||
|
||||
### 2.1 更新openspec/project.md
|
||||
- 详细描述项目目的和目标
|
||||
- 明确技术栈:Vue 3.x、Node.js、Vite、Redis
|
||||
- 定义代码风格、架构模式、测试策略和Git工作流
|
||||
- 记录领域上下文和重要约束
|
||||
- 文档外部依赖
|
||||
|
||||
### 2.2 创建规格文档
|
||||
- 在openspec/specs/目录下创建核心能力规格
|
||||
- **logging/spec.md**: 日志读取和展示功能规格
|
||||
- **command/spec.md**: 控制台指令发送功能规格
|
||||
- **redis-connection/spec.md**: Redis连接管理规格
|
||||
|
||||
### 2.3 创建设计文档
|
||||
- 在openspec/specs/目录下为每个核心能力创建设计文档
|
||||
- **logging/design.md**: 日志功能技术设计
|
||||
- **command/design.md**: 指令功能技术设计
|
||||
- **redis-connection/design.md**: Redis连接管理设计
|
||||
|
||||
## 3. 编写README.md
|
||||
|
||||
### 3.1 项目概述
|
||||
- 项目名称、描述和主要功能
|
||||
- 技术栈和架构说明
|
||||
|
||||
### 3.2 快速开始
|
||||
- 环境要求
|
||||
- 安装和运行步骤
|
||||
|
||||
### 3.3 项目结构
|
||||
- 目录结构说明
|
||||
- 核心文件功能介绍
|
||||
|
||||
### 3.4 功能模块
|
||||
- 日志记录展示功能
|
||||
- 控制台指令发送功能
|
||||
|
||||
### 3.5 开发指南
|
||||
- 代码风格规范
|
||||
- 开发流程
|
||||
- 测试指南
|
||||
|
||||
### 3.6 部署说明
|
||||
- 生产环境部署步骤
|
||||
- 配置说明
|
||||
|
||||
## 4. 编写框架约束文件
|
||||
|
||||
### 4.1 ESLint配置
|
||||
- **.eslintrc.js**: 配置代码质量检查规则
|
||||
|
||||
### 4.2 Prettier配置
|
||||
- **.prettierrc**: 配置代码格式化规则
|
||||
|
||||
### 4.3 编辑器配置
|
||||
- **.vscode/settings.json**: VS Code编辑器配置
|
||||
|
||||
## 5. 目录结构规划
|
||||
|
||||
```
|
||||
Web_BLS_ProjectConsole/
|
||||
├── .github/
|
||||
│ └── prompts/
|
||||
├── .vscode/
|
||||
│ └── settings.json
|
||||
├── openspec/
|
||||
│ ├── project.md
|
||||
│ ├── AGENTS.md
|
||||
│ └── specs/
|
||||
│ ├── logging/
|
||||
│ │ ├── spec.md
|
||||
│ │ └── design.md
|
||||
│ ├── command/
|
||||
│ │ ├── spec.md
|
||||
│ │ └── design.md
|
||||
│ └── redis-connection/
|
||||
│ ├── spec.md
|
||||
│ └── design.md
|
||||
├── public/
|
||||
│ └── index.html
|
||||
├── src/
|
||||
│ ├── frontend/
|
||||
│ │ ├── assets/
|
||||
│ │ ├── components/
|
||||
│ │ ├── views/
|
||||
│ │ ├── router/
|
||||
│ │ ├── store/
|
||||
│ │ └── main.js
|
||||
│ └── backend/
|
||||
│ ├── server.js
|
||||
│ ├── routes/
|
||||
│ ├── services/
|
||||
│ └── config/
|
||||
├── .eslintrc.js
|
||||
├── .gitignore
|
||||
├── .prettierrc
|
||||
├── vite.config.js
|
||||
├── package.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 6. 实施步骤
|
||||
|
||||
1. 初始化项目,创建package.json和vite.config.js
|
||||
2. 安装核心依赖
|
||||
3. 完善openspec/project.md
|
||||
4. 创建核心能力规格文档和设计文档
|
||||
5. 编写README.md
|
||||
6. 配置ESLint和Prettier
|
||||
7. 创建编辑器配置文件
|
||||
8. 创建基本目录结构
|
||||
|
||||
这个计划将为项目搭建一个完整的基础架构,包括文档、配置和依赖管理,为后续实现具体功能做好准备。
|
||||
18
AGENTS.md
Normal file
18
AGENTS.md
Normal file
@@ -0,0 +1,18 @@
|
||||
<!-- OPENSPEC:START -->
|
||||
# OpenSpec Instructions
|
||||
|
||||
These instructions are for AI assistants working in this project.
|
||||
|
||||
Always open `@/openspec/AGENTS.md` when the request:
|
||||
- Mentions planning or proposals (words like proposal, spec, change, plan)
|
||||
- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
|
||||
- Sounds ambiguous and you need the authoritative spec before coding
|
||||
|
||||
Use `@/openspec/AGENTS.md` to learn:
|
||||
- How to create and apply change proposals
|
||||
- Spec format and conventions
|
||||
- Project structure and guidelines
|
||||
|
||||
Keep this managed block so 'openspec update' can refresh the instructions.
|
||||
|
||||
<!-- OPENSPEC:END -->
|
||||
339
README.md
Normal file
339
README.md
Normal file
@@ -0,0 +1,339 @@
|
||||
# BLS Project Console
|
||||
|
||||
## 项目概述
|
||||
|
||||
BLS Project Console是一个前后端分离的Node.js项目,用于从Redis队列读取日志记录并展示在控制台界面中,同时提供发送控制台指令到Redis队列的功能,以便其他程序读取和执行。
|
||||
|
||||
### 主要功能
|
||||
|
||||
- **日志记录展示**:从Redis队列实时读取日志记录,以友好的格式展示在控制台界面中
|
||||
- **控制台指令发送**:允许用户发送控制台指令到Redis队列,供其他程序读取和执行
|
||||
- **实时更新**:日志记录和指令状态实时更新,提供良好的用户体验
|
||||
- **响应式设计**:适配不同屏幕尺寸,提供良好的移动端体验
|
||||
|
||||
## 技术栈
|
||||
|
||||
### 前端
|
||||
- Vue 3.x:渐进式JavaScript框架
|
||||
- Vue Router:前端路由管理
|
||||
- Axios:HTTP客户端,用于与后端API通信
|
||||
- CSS3:样式设计
|
||||
|
||||
### 后端
|
||||
- Node.js:JavaScript运行时环境
|
||||
- Express:Web应用框架
|
||||
- Redis客户端:用于与Redis服务器通信
|
||||
- CORS:跨域资源共享中间件
|
||||
|
||||
### 构建工具和开发工具
|
||||
- Vite:现代化前端构建工具
|
||||
- ESLint:JavaScript代码质量检查工具
|
||||
- Prettier:代码格式化工具
|
||||
- nodemon:Node.js开发服务器,支持热重载
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 环境要求
|
||||
|
||||
- Node.js >= 16.x
|
||||
- npm >= 8.x
|
||||
- Redis >= 6.x
|
||||
|
||||
### 安装步骤
|
||||
|
||||
1. 克隆项目代码
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd Web_BLS_ProjectConsole
|
||||
```
|
||||
|
||||
2. 安装依赖
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. 配置环境变量
|
||||
|
||||
创建 `.env` 文件,配置Redis连接参数:
|
||||
|
||||
```env
|
||||
# Redis配置
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=
|
||||
REDIS_DB=0
|
||||
```
|
||||
|
||||
### 运行项目
|
||||
|
||||
#### 开发模式
|
||||
|
||||
同时启动前端和后端开发服务器:
|
||||
|
||||
```bash
|
||||
# 启动前端开发服务器(端口3000)
|
||||
npm run dev
|
||||
|
||||
# 启动后端开发服务器(端口3001)
|
||||
npm run start:dev
|
||||
```
|
||||
|
||||
#### 生产模式
|
||||
|
||||
1. 构建前端项目
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
2. 启动后端服务器
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
Web_BLS_ProjectConsole/
|
||||
├── .github/ # GitHub配置文件
|
||||
│ └── prompts/ # OpenSpec提示文件
|
||||
├── openspec/ # OpenSpec规格文档
|
||||
│ ├── project.md # 项目概述和规范
|
||||
│ ├── AGENTS.md # AI代理指令
|
||||
│ └── specs/ # 核心能力规格
|
||||
│ ├── logging/ # 日志功能规格
|
||||
│ ├── command/ # 指令功能规格
|
||||
│ └── redis-connection/ # Redis连接规格
|
||||
├── public/ # 静态资源文件
|
||||
│ └── index.html # HTML入口文件
|
||||
├── src/ # 源代码
|
||||
│ ├── frontend/ # 前端代码
|
||||
│ │ ├── assets/ # 静态资源
|
||||
│ │ ├── components/ # Vue组件
|
||||
│ │ ├── views/ # 页面视图
|
||||
│ │ ├── router/ # 路由配置
|
||||
│ │ ├── store/ # 状态管理
|
||||
│ │ ├── App.vue # 根组件
|
||||
│ │ └── main.js # 入口文件
|
||||
│ └── backend/ # 后端代码
|
||||
│ ├── routes/ # API路由
|
||||
│ ├── services/ # 业务逻辑
|
||||
│ ├── config/ # 配置文件
|
||||
│ └── server.js # 服务器入口文件
|
||||
├── .eslintrc.js # ESLint配置
|
||||
├── .gitignore # Git忽略文件
|
||||
├── .prettierrc # Prettier配置
|
||||
├── vite.config.js # Vite配置
|
||||
├── package.json # 项目配置和依赖管理
|
||||
└── README.md # 项目说明文档
|
||||
```
|
||||
|
||||
## 功能模块
|
||||
|
||||
### 日志记录展示
|
||||
|
||||
日志记录展示模块负责从Redis队列读取日志记录,并以友好的格式展示在控制台界面中。
|
||||
|
||||
#### 主要功能
|
||||
|
||||
- 实时读取Redis队列中的日志记录
|
||||
- 以列表形式展示日志记录,包含时间戳、日志级别和消息内容
|
||||
- 支持按日志级别和时间范围过滤日志
|
||||
- 自动滚动到最新日志(可选)
|
||||
- 支持查看历史日志
|
||||
|
||||
#### 技术实现
|
||||
|
||||
- 使用Redis List作为日志队列
|
||||
- 使用Server-Sent Events(SSE)实现实时更新
|
||||
- 前端使用Vue组件化开发,实现日志列表和过滤功能
|
||||
|
||||
### 控制台指令发送
|
||||
|
||||
控制台指令发送模块允许用户发送控制台指令到Redis队列,供其他程序读取和执行。
|
||||
|
||||
#### 主要功能
|
||||
|
||||
- 提供指令输入框,允许用户输入控制台指令
|
||||
- 支持指令验证,确保指令格式正确
|
||||
- 支持发送指令到Redis队列
|
||||
- 显示指令发送状态和结果
|
||||
- 维护指令历史记录,支持重新发送历史指令
|
||||
|
||||
#### 技术实现
|
||||
|
||||
- 使用Redis List作为指令队列
|
||||
- 前端使用Vue组件化开发,实现指令表单和历史记录功能
|
||||
- 后端实现指令验证和发送逻辑
|
||||
|
||||
## 开发指南
|
||||
|
||||
### 代码风格规范
|
||||
|
||||
- **JavaScript**:使用ES模块语法(import/export)
|
||||
- **Vue**:使用Composition API
|
||||
- **命名规范**:
|
||||
- 文件名:小驼峰命名(如:logView.vue)
|
||||
- 组件名:大驼峰命名(如:LogView)
|
||||
- 变量名:小驼峰命名
|
||||
- 常量名:大写蛇形命名(如:REDIS_QUEUE_NAME)
|
||||
- **代码格式化**:使用Prettier自动格式化
|
||||
- **代码质量**:使用ESLint进行静态代码检查
|
||||
|
||||
### 开发流程
|
||||
|
||||
1. 创建分支:从develop分支创建功能分支
|
||||
|
||||
```bash
|
||||
git checkout develop
|
||||
git checkout -b feature/feature-name
|
||||
```
|
||||
|
||||
2. 开发功能:实现功能代码,确保代码质量
|
||||
|
||||
3. 提交代码:使用Conventional Commits规范提交代码
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: add feature-name"
|
||||
```
|
||||
|
||||
4. 推送代码:将功能分支推送到远程仓库
|
||||
|
||||
```bash
|
||||
git push origin feature/feature-name
|
||||
```
|
||||
|
||||
5. 创建PR:创建Pull Request,请求合并到develop分支
|
||||
|
||||
6. 代码审查:等待团队成员代码审查
|
||||
|
||||
7. 合并代码:代码审查通过后,合并到develop分支
|
||||
|
||||
### 测试指南
|
||||
|
||||
#### 单元测试
|
||||
|
||||
```bash
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
#### 集成测试
|
||||
|
||||
```bash
|
||||
npm run test:integration
|
||||
```
|
||||
|
||||
#### 端到端测试
|
||||
|
||||
```bash
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
#### 代码质量检查
|
||||
|
||||
```bash
|
||||
# ESLint检查
|
||||
npm run lint
|
||||
|
||||
# Prettier格式化
|
||||
npm run format
|
||||
```
|
||||
|
||||
## 部署说明
|
||||
|
||||
### 生产环境部署
|
||||
|
||||
1. 配置生产环境变量
|
||||
|
||||
```env
|
||||
# Redis配置
|
||||
REDIS_HOST=redis-server
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=your-redis-password
|
||||
REDIS_DB=0
|
||||
|
||||
# 服务器配置
|
||||
PORT=3001
|
||||
NODE_ENV=production
|
||||
```
|
||||
|
||||
2. 构建前端项目
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
3. 启动后端服务器
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
### Docker部署(可选)
|
||||
|
||||
创建Dockerfile:
|
||||
|
||||
```dockerfile
|
||||
FROM node:16-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm install --production
|
||||
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
EXPOSE 3001
|
||||
|
||||
CMD ["npm", "start"]
|
||||
```
|
||||
|
||||
构建Docker镜像:
|
||||
|
||||
```bash
|
||||
docker build -t bls-project-console .
|
||||
```
|
||||
|
||||
运行Docker容器:
|
||||
|
||||
```bash
|
||||
docker run -p 3001:3001 --env-file .env bls-project-console
|
||||
```
|
||||
|
||||
## 配置说明
|
||||
|
||||
### Redis配置
|
||||
|
||||
| 配置项 | 环境变量 | 默认值 | 说明 |
|
||||
|--------|----------|--------|------|
|
||||
| 主机名 | REDIS_HOST | localhost | Redis服务器主机名 |
|
||||
| 端口 | REDIS_PORT | 6379 | Redis服务器端口 |
|
||||
| 密码 | REDIS_PASSWORD | | Redis服务器密码 |
|
||||
| 数据库索引 | REDIS_DB | 0 | Redis数据库索引 |
|
||||
| 连接超时 | REDIS_CONNECT_TIMEOUT | 10000 | 连接超时时间(毫秒) |
|
||||
| 最大重试次数 | REDIS_MAX_RETRIES | 3 | 最大重试次数 |
|
||||
| 重连策略 | REDIS_RECONNECT_STRATEGY | exponential | 重连策略(exponential/fixed) |
|
||||
| 重连间隔 | REDIS_RECONNECT_INTERVAL | 1000 | 重连间隔(毫秒) |
|
||||
| 最大重连间隔 | REDIS_MAX_RECONNECT_INTERVAL | 30000 | 最大重连间隔(毫秒) |
|
||||
|
||||
### 服务器配置
|
||||
|
||||
| 配置项 | 环境变量 | 默认值 | 说明 |
|
||||
|--------|----------|--------|------|
|
||||
| 端口 | PORT | 3001 | 服务器端口 |
|
||||
| 环境 | NODE_ENV | development | 运行环境(development/production) |
|
||||
|
||||
## 贡献指南
|
||||
|
||||
1. Fork项目代码
|
||||
2. 创建功能分支
|
||||
3. 实现功能或修复bug
|
||||
4. 提交代码,使用Conventional Commits规范
|
||||
5. 创建Pull Request
|
||||
6. 等待代码审查
|
||||
7. 代码审查通过后,合并到主分支
|
||||
456
openspec/AGENTS.md
Normal file
456
openspec/AGENTS.md
Normal file
@@ -0,0 +1,456 @@
|
||||
# OpenSpec Instructions
|
||||
|
||||
Instructions for AI coding assistants using OpenSpec for spec-driven development.
|
||||
|
||||
## TL;DR Quick Checklist
|
||||
|
||||
- Search existing work: `openspec spec list --long`, `openspec list` (use `rg` only for full-text search)
|
||||
- Decide scope: new capability vs modify existing capability
|
||||
- Pick a unique `change-id`: kebab-case, verb-led (`add-`, `update-`, `remove-`, `refactor-`)
|
||||
- Scaffold: `proposal.md`, `tasks.md`, `design.md` (only if needed), and delta specs per affected capability
|
||||
- Write deltas: use `## ADDED|MODIFIED|REMOVED|RENAMED Requirements`; include at least one `#### Scenario:` per requirement
|
||||
- Validate: `openspec validate [change-id] --strict` and fix issues
|
||||
- Request approval: Do not start implementation until proposal is approved
|
||||
|
||||
## Three-Stage Workflow
|
||||
|
||||
### Stage 1: Creating Changes
|
||||
Create proposal when you need to:
|
||||
- Add features or functionality
|
||||
- Make breaking changes (API, schema)
|
||||
- Change architecture or patterns
|
||||
- Optimize performance (changes behavior)
|
||||
- Update security patterns
|
||||
|
||||
Triggers (examples):
|
||||
- "Help me create a change proposal"
|
||||
- "Help me plan a change"
|
||||
- "Help me create a proposal"
|
||||
- "I want to create a spec proposal"
|
||||
- "I want to create a spec"
|
||||
|
||||
Loose matching guidance:
|
||||
- Contains one of: `proposal`, `change`, `spec`
|
||||
- With one of: `create`, `plan`, `make`, `start`, `help`
|
||||
|
||||
Skip proposal for:
|
||||
- Bug fixes (restore intended behavior)
|
||||
- Typos, formatting, comments
|
||||
- Dependency updates (non-breaking)
|
||||
- Configuration changes
|
||||
- Tests for existing behavior
|
||||
|
||||
**Workflow**
|
||||
1. Review `openspec/project.md`, `openspec list`, and `openspec list --specs` to understand current context.
|
||||
2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, optional `design.md`, and spec deltas under `openspec/changes/<id>/`.
|
||||
3. Draft spec deltas using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement.
|
||||
4. Run `openspec validate <id> --strict` and resolve any issues before sharing the proposal.
|
||||
|
||||
### Stage 2: Implementing Changes
|
||||
Track these steps as TODOs and complete them one by one.
|
||||
1. **Read proposal.md** - Understand what's being built
|
||||
2. **Read design.md** (if exists) - Review technical decisions
|
||||
3. **Read tasks.md** - Get implementation checklist
|
||||
4. **Implement tasks sequentially** - Complete in order
|
||||
5. **Confirm completion** - Ensure every item in `tasks.md` is finished before updating statuses
|
||||
6. **Update checklist** - After all work is done, set every task to `- [x]` so the list reflects reality
|
||||
7. **Approval gate** - Do not start implementation until the proposal is reviewed and approved
|
||||
|
||||
### Stage 3: Archiving Changes
|
||||
After deployment, create separate PR to:
|
||||
- Move `changes/[name]/` → `changes/archive/YYYY-MM-DD-[name]/`
|
||||
- Update `specs/` if capabilities changed
|
||||
- Use `openspec archive <change-id> --skip-specs --yes` for tooling-only changes (always pass the change ID explicitly)
|
||||
- Run `openspec validate --strict` to confirm the archived change passes checks
|
||||
|
||||
## Before Any Task
|
||||
|
||||
**Context Checklist:**
|
||||
- [ ] Read relevant specs in `specs/[capability]/spec.md`
|
||||
- [ ] Check pending changes in `changes/` for conflicts
|
||||
- [ ] Read `openspec/project.md` for conventions
|
||||
- [ ] Run `openspec list` to see active changes
|
||||
- [ ] Run `openspec list --specs` to see existing capabilities
|
||||
|
||||
**Before Creating Specs:**
|
||||
- Always check if capability already exists
|
||||
- Prefer modifying existing specs over creating duplicates
|
||||
- Use `openspec show [spec]` to review current state
|
||||
- If request is ambiguous, ask 1–2 clarifying questions before scaffolding
|
||||
|
||||
### Search Guidance
|
||||
- Enumerate specs: `openspec spec list --long` (or `--json` for scripts)
|
||||
- Enumerate changes: `openspec list` (or `openspec change list --json` - deprecated but available)
|
||||
- Show details:
|
||||
- Spec: `openspec show <spec-id> --type spec` (use `--json` for filters)
|
||||
- Change: `openspec show <change-id> --json --deltas-only`
|
||||
- Full-text search (use ripgrep): `rg -n "Requirement:|Scenario:" openspec/specs`
|
||||
|
||||
## Quick Start
|
||||
|
||||
### CLI Commands
|
||||
|
||||
```bash
|
||||
# Essential commands
|
||||
openspec list # List active changes
|
||||
openspec list --specs # List specifications
|
||||
openspec show [item] # Display change or spec
|
||||
openspec validate [item] # Validate changes or specs
|
||||
openspec archive <change-id> [--yes|-y] # Archive after deployment (add --yes for non-interactive runs)
|
||||
|
||||
# Project management
|
||||
openspec init [path] # Initialize OpenSpec
|
||||
openspec update [path] # Update instruction files
|
||||
|
||||
# Interactive mode
|
||||
openspec show # Prompts for selection
|
||||
openspec validate # Bulk validation mode
|
||||
|
||||
# Debugging
|
||||
openspec show [change] --json --deltas-only
|
||||
openspec validate [change] --strict
|
||||
```
|
||||
|
||||
### Command Flags
|
||||
|
||||
- `--json` - Machine-readable output
|
||||
- `--type change|spec` - Disambiguate items
|
||||
- `--strict` - Comprehensive validation
|
||||
- `--no-interactive` - Disable prompts
|
||||
- `--skip-specs` - Archive without spec updates
|
||||
- `--yes`/`-y` - Skip confirmation prompts (non-interactive archive)
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
openspec/
|
||||
├── project.md # Project conventions
|
||||
├── specs/ # Current truth - what IS built
|
||||
│ └── [capability]/ # Single focused capability
|
||||
│ ├── spec.md # Requirements and scenarios
|
||||
│ └── design.md # Technical patterns
|
||||
├── changes/ # Proposals - what SHOULD change
|
||||
│ ├── [change-name]/
|
||||
│ │ ├── proposal.md # Why, what, impact
|
||||
│ │ ├── tasks.md # Implementation checklist
|
||||
│ │ ├── design.md # Technical decisions (optional; see criteria)
|
||||
│ │ └── specs/ # Delta changes
|
||||
│ │ └── [capability]/
|
||||
│ │ └── spec.md # ADDED/MODIFIED/REMOVED
|
||||
│ └── archive/ # Completed changes
|
||||
```
|
||||
|
||||
## Creating Change Proposals
|
||||
|
||||
### Decision Tree
|
||||
|
||||
```
|
||||
New request?
|
||||
├─ Bug fix restoring spec behavior? → Fix directly
|
||||
├─ Typo/format/comment? → Fix directly
|
||||
├─ New feature/capability? → Create proposal
|
||||
├─ Breaking change? → Create proposal
|
||||
├─ Architecture change? → Create proposal
|
||||
└─ Unclear? → Create proposal (safer)
|
||||
```
|
||||
|
||||
### Proposal Structure
|
||||
|
||||
1. **Create directory:** `changes/[change-id]/` (kebab-case, verb-led, unique)
|
||||
|
||||
2. **Write proposal.md:**
|
||||
```markdown
|
||||
# Change: [Brief description of change]
|
||||
|
||||
## Why
|
||||
[1-2 sentences on problem/opportunity]
|
||||
|
||||
## What Changes
|
||||
- [Bullet list of changes]
|
||||
- [Mark breaking changes with **BREAKING**]
|
||||
|
||||
## Impact
|
||||
- Affected specs: [list capabilities]
|
||||
- Affected code: [key files/systems]
|
||||
```
|
||||
|
||||
3. **Create spec deltas:** `specs/[capability]/spec.md`
|
||||
```markdown
|
||||
## ADDED Requirements
|
||||
### Requirement: New Feature
|
||||
The system SHALL provide...
|
||||
|
||||
#### Scenario: Success case
|
||||
- **WHEN** user performs action
|
||||
- **THEN** expected result
|
||||
|
||||
## MODIFIED Requirements
|
||||
### Requirement: Existing Feature
|
||||
[Complete modified requirement]
|
||||
|
||||
## REMOVED Requirements
|
||||
### Requirement: Old Feature
|
||||
**Reason**: [Why removing]
|
||||
**Migration**: [How to handle]
|
||||
```
|
||||
If multiple capabilities are affected, create multiple delta files under `changes/[change-id]/specs/<capability>/spec.md`—one per capability.
|
||||
|
||||
4. **Create tasks.md:**
|
||||
```markdown
|
||||
## 1. Implementation
|
||||
- [ ] 1.1 Create database schema
|
||||
- [ ] 1.2 Implement API endpoint
|
||||
- [ ] 1.3 Add frontend component
|
||||
- [ ] 1.4 Write tests
|
||||
```
|
||||
|
||||
5. **Create design.md when needed:**
|
||||
Create `design.md` if any of the following apply; otherwise omit it:
|
||||
- Cross-cutting change (multiple services/modules) or a new architectural pattern
|
||||
- New external dependency or significant data model changes
|
||||
- Security, performance, or migration complexity
|
||||
- Ambiguity that benefits from technical decisions before coding
|
||||
|
||||
Minimal `design.md` skeleton:
|
||||
```markdown
|
||||
## Context
|
||||
[Background, constraints, stakeholders]
|
||||
|
||||
## Goals / Non-Goals
|
||||
- Goals: [...]
|
||||
- Non-Goals: [...]
|
||||
|
||||
## Decisions
|
||||
- Decision: [What and why]
|
||||
- Alternatives considered: [Options + rationale]
|
||||
|
||||
## Risks / Trade-offs
|
||||
- [Risk] → Mitigation
|
||||
|
||||
## Migration Plan
|
||||
[Steps, rollback]
|
||||
|
||||
## Open Questions
|
||||
- [...]
|
||||
```
|
||||
|
||||
## Spec File Format
|
||||
|
||||
### Critical: Scenario Formatting
|
||||
|
||||
**CORRECT** (use #### headers):
|
||||
```markdown
|
||||
#### Scenario: User login success
|
||||
- **WHEN** valid credentials provided
|
||||
- **THEN** return JWT token
|
||||
```
|
||||
|
||||
**WRONG** (don't use bullets or bold):
|
||||
```markdown
|
||||
- **Scenario: User login** ❌
|
||||
**Scenario**: User login ❌
|
||||
### Scenario: User login ❌
|
||||
```
|
||||
|
||||
Every requirement MUST have at least one scenario.
|
||||
|
||||
### Requirement Wording
|
||||
- Use SHALL/MUST for normative requirements (avoid should/may unless intentionally non-normative)
|
||||
|
||||
### Delta Operations
|
||||
|
||||
- `## ADDED Requirements` - New capabilities
|
||||
- `## MODIFIED Requirements` - Changed behavior
|
||||
- `## REMOVED Requirements` - Deprecated features
|
||||
- `## RENAMED Requirements` - Name changes
|
||||
|
||||
Headers matched with `trim(header)` - whitespace ignored.
|
||||
|
||||
#### When to use ADDED vs MODIFIED
|
||||
- ADDED: Introduces a new capability or sub-capability that can stand alone as a requirement. Prefer ADDED when the change is orthogonal (e.g., adding "Slash Command Configuration") rather than altering the semantics of an existing requirement.
|
||||
- MODIFIED: Changes the behavior, scope, or acceptance criteria of an existing requirement. Always paste the full, updated requirement content (header + all scenarios). The archiver will replace the entire requirement with what you provide here; partial deltas will drop previous details.
|
||||
- RENAMED: Use when only the name changes. If you also change behavior, use RENAMED (name) plus MODIFIED (content) referencing the new name.
|
||||
|
||||
Common pitfall: Using MODIFIED to add a new concern without including the previous text. This causes loss of detail at archive time. If you aren’t explicitly changing the existing requirement, add a new requirement under ADDED instead.
|
||||
|
||||
Authoring a MODIFIED requirement correctly:
|
||||
1) Locate the existing requirement in `openspec/specs/<capability>/spec.md`.
|
||||
2) Copy the entire requirement block (from `### Requirement: ...` through its scenarios).
|
||||
3) Paste it under `## MODIFIED Requirements` and edit to reflect the new behavior.
|
||||
4) Ensure the header text matches exactly (whitespace-insensitive) and keep at least one `#### Scenario:`.
|
||||
|
||||
Example for RENAMED:
|
||||
```markdown
|
||||
## RENAMED Requirements
|
||||
- FROM: `### Requirement: Login`
|
||||
- TO: `### Requirement: User Authentication`
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Errors
|
||||
|
||||
**"Change must have at least one delta"**
|
||||
- Check `changes/[name]/specs/` exists with .md files
|
||||
- Verify files have operation prefixes (## ADDED Requirements)
|
||||
|
||||
**"Requirement must have at least one scenario"**
|
||||
- Check scenarios use `#### Scenario:` format (4 hashtags)
|
||||
- Don't use bullet points or bold for scenario headers
|
||||
|
||||
**Silent scenario parsing failures**
|
||||
- Exact format required: `#### Scenario: Name`
|
||||
- Debug with: `openspec show [change] --json --deltas-only`
|
||||
|
||||
### Validation Tips
|
||||
|
||||
```bash
|
||||
# Always use strict mode for comprehensive checks
|
||||
openspec validate [change] --strict
|
||||
|
||||
# Debug delta parsing
|
||||
openspec show [change] --json | jq '.deltas'
|
||||
|
||||
# Check specific requirement
|
||||
openspec show [spec] --json -r 1
|
||||
```
|
||||
|
||||
## Happy Path Script
|
||||
|
||||
```bash
|
||||
# 1) Explore current state
|
||||
openspec spec list --long
|
||||
openspec list
|
||||
# Optional full-text search:
|
||||
# rg -n "Requirement:|Scenario:" openspec/specs
|
||||
# rg -n "^#|Requirement:" openspec/changes
|
||||
|
||||
# 2) Choose change id and scaffold
|
||||
CHANGE=add-two-factor-auth
|
||||
mkdir -p openspec/changes/$CHANGE/{specs/auth}
|
||||
printf "## Why\n...\n\n## What Changes\n- ...\n\n## Impact\n- ...\n" > openspec/changes/$CHANGE/proposal.md
|
||||
printf "## 1. Implementation\n- [ ] 1.1 ...\n" > openspec/changes/$CHANGE/tasks.md
|
||||
|
||||
# 3) Add deltas (example)
|
||||
cat > openspec/changes/$CHANGE/specs/auth/spec.md << 'EOF'
|
||||
## ADDED Requirements
|
||||
### Requirement: Two-Factor Authentication
|
||||
Users MUST provide a second factor during login.
|
||||
|
||||
#### Scenario: OTP required
|
||||
- **WHEN** valid credentials are provided
|
||||
- **THEN** an OTP challenge is required
|
||||
EOF
|
||||
|
||||
# 4) Validate
|
||||
openspec validate $CHANGE --strict
|
||||
```
|
||||
|
||||
## Multi-Capability Example
|
||||
|
||||
```
|
||||
openspec/changes/add-2fa-notify/
|
||||
├── proposal.md
|
||||
├── tasks.md
|
||||
└── specs/
|
||||
├── auth/
|
||||
│ └── spec.md # ADDED: Two-Factor Authentication
|
||||
└── notifications/
|
||||
└── spec.md # ADDED: OTP email notification
|
||||
```
|
||||
|
||||
auth/spec.md
|
||||
```markdown
|
||||
## ADDED Requirements
|
||||
### Requirement: Two-Factor Authentication
|
||||
...
|
||||
```
|
||||
|
||||
notifications/spec.md
|
||||
```markdown
|
||||
## ADDED Requirements
|
||||
### Requirement: OTP Email Notification
|
||||
...
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Simplicity First
|
||||
- Default to <100 lines of new code
|
||||
- Single-file implementations until proven insufficient
|
||||
- Avoid frameworks without clear justification
|
||||
- Choose boring, proven patterns
|
||||
|
||||
### Complexity Triggers
|
||||
Only add complexity with:
|
||||
- Performance data showing current solution too slow
|
||||
- Concrete scale requirements (>1000 users, >100MB data)
|
||||
- Multiple proven use cases requiring abstraction
|
||||
|
||||
### Clear References
|
||||
- Use `file.ts:42` format for code locations
|
||||
- Reference specs as `specs/auth/spec.md`
|
||||
- Link related changes and PRs
|
||||
|
||||
### Capability Naming
|
||||
- Use verb-noun: `user-auth`, `payment-capture`
|
||||
- Single purpose per capability
|
||||
- 10-minute understandability rule
|
||||
- Split if description needs "AND"
|
||||
|
||||
### Change ID Naming
|
||||
- Use kebab-case, short and descriptive: `add-two-factor-auth`
|
||||
- Prefer verb-led prefixes: `add-`, `update-`, `remove-`, `refactor-`
|
||||
- Ensure uniqueness; if taken, append `-2`, `-3`, etc.
|
||||
|
||||
## Tool Selection Guide
|
||||
|
||||
| Task | Tool | Why |
|
||||
|------|------|-----|
|
||||
| Find files by pattern | Glob | Fast pattern matching |
|
||||
| Search code content | Grep | Optimized regex search |
|
||||
| Read specific files | Read | Direct file access |
|
||||
| Explore unknown scope | Task | Multi-step investigation |
|
||||
|
||||
## Error Recovery
|
||||
|
||||
### Change Conflicts
|
||||
1. Run `openspec list` to see active changes
|
||||
2. Check for overlapping specs
|
||||
3. Coordinate with change owners
|
||||
4. Consider combining proposals
|
||||
|
||||
### Validation Failures
|
||||
1. Run with `--strict` flag
|
||||
2. Check JSON output for details
|
||||
3. Verify spec file format
|
||||
4. Ensure scenarios properly formatted
|
||||
|
||||
### Missing Context
|
||||
1. Read project.md first
|
||||
2. Check related specs
|
||||
3. Review recent archives
|
||||
4. Ask for clarification
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Stage Indicators
|
||||
- `changes/` - Proposed, not yet built
|
||||
- `specs/` - Built and deployed
|
||||
- `archive/` - Completed changes
|
||||
|
||||
### File Purposes
|
||||
- `proposal.md` - Why and what
|
||||
- `tasks.md` - Implementation steps
|
||||
- `design.md` - Technical decisions
|
||||
- `spec.md` - Requirements and behavior
|
||||
|
||||
### CLI Essentials
|
||||
```bash
|
||||
openspec list # What's in progress?
|
||||
openspec show [item] # View details
|
||||
openspec validate --strict # Is it correct?
|
||||
openspec archive <change-id> [--yes|-y] # Mark complete (add --yes for automation)
|
||||
```
|
||||
|
||||
Remember: Specs are truth. Changes are proposals. Keep them in sync.
|
||||
70
openspec/project.md
Normal file
70
openspec/project.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Project Context
|
||||
|
||||
## Purpose
|
||||
BLS Project Console是一个前后端分离的Node.js项目,用于从Redis队列读取日志记录并展示在控制台界面中,同时提供发送控制台指令到Redis队列的功能,以便其他程序读取和执行。
|
||||
|
||||
## Tech Stack
|
||||
- **前端**: Vue 3.x, Vue Router, Axios, CSS3
|
||||
- **后端**: Node.js, Express, Redis客户端, CORS
|
||||
- **构建工具**: Vite
|
||||
- **开发工具**: ESLint, Prettier, nodemon
|
||||
|
||||
## Project Conventions
|
||||
|
||||
### Code Style
|
||||
- **JavaScript**: 使用ES模块语法(import/export)
|
||||
- **Vue**: 使用Composition API
|
||||
- **命名规范**:
|
||||
- 文件名: 小驼峰命名(如: logView.vue)
|
||||
- 组件名: 大驼峰命名(如: LogView)
|
||||
- 变量名: 小驼峰命名
|
||||
- 常量名: 大写蛇形命名(如: REDIS_QUEUE_NAME)
|
||||
- **代码格式化**: 使用Prettier自动格式化
|
||||
- **代码质量**: 使用ESLint进行静态代码检查
|
||||
|
||||
### Architecture Patterns
|
||||
- **前后端分离**: 前端和后端独立部署,通过RESTful API通信
|
||||
- **MVC架构**: 后端使用Model-View-Controller模式
|
||||
- **组件化开发**: 前端采用Vue组件化开发
|
||||
- **分层设计**:
|
||||
- 前端: 视图层、路由层、服务层
|
||||
- 后端: 路由层、服务层、数据访问层
|
||||
|
||||
### Testing Strategy
|
||||
- **单元测试**: 对核心功能模块进行单元测试
|
||||
- **集成测试**: 测试API接口和Redis交互
|
||||
- **端到端测试**: 测试完整的用户流程
|
||||
- **测试框架**: Jest (后端), Vitest (前端)
|
||||
|
||||
### Git Workflow
|
||||
- **分支策略**: Git Flow
|
||||
- main: 生产分支
|
||||
- develop: 开发分支
|
||||
- feature/: 功能分支
|
||||
- hotfix/: 热修复分支
|
||||
- **提交规范**: 使用Conventional Commits
|
||||
- feat: 新功能
|
||||
- fix: 修复bug
|
||||
- docs: 文档变更
|
||||
- style: 代码格式变更
|
||||
- refactor: 代码重构
|
||||
- test: 测试相关变更
|
||||
- chore: 构建或依赖更新
|
||||
|
||||
## Domain Context
|
||||
- **Redis队列**: 用于存储日志记录和控制台指令的消息队列
|
||||
- **日志记录**: 其他程序写入Redis队列的日志信息,包含时间戳、日志级别和消息内容
|
||||
- **控制台指令**: 从控制台发送到Redis队列的命令,供其他程序读取和执行
|
||||
- **实时更新**: 控制台需要实时从Redis队列获取新的日志记录
|
||||
|
||||
## Important Constraints
|
||||
- **性能要求**: 控制台需要能够处理大量日志记录的实时更新
|
||||
- **可靠性**: Redis连接需要具备重连机制,确保系统稳定运行
|
||||
- **安全性**: API接口需要适当的访问控制
|
||||
- **可扩展性**: 系统设计应支持未来功能扩展
|
||||
|
||||
## External Dependencies
|
||||
- **Redis**: 用于存储日志记录和控制台指令的消息队列服务
|
||||
- 版本: 6.x+
|
||||
- 连接方式: Redis客户端(redis@^4.6.10)
|
||||
- 主要用途: 日志队列和指令队列
|
||||
123
openspec/specs/command/design.md
Normal file
123
openspec/specs/command/design.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Command Capability Design
|
||||
|
||||
## Context
|
||||
This design document describes the technical implementation of the command capability for the BLS Project Console, which allows users to send console commands to Redis queues for other programs to read and execute.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
### Goals
|
||||
- Implement command sending to Redis queues
|
||||
- Provide command validation and error handling
|
||||
- Maintain a history of sent commands
|
||||
- Handle command responses from Redis
|
||||
- Ensure high performance and reliability
|
||||
|
||||
### Non-Goals
|
||||
- Command execution or processing
|
||||
- Complex command syntax highlighting
|
||||
- Advanced command editing capabilities
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision: Redis Queue Implementation
|
||||
- **What**: Use Redis List as the queue data structure
|
||||
- **Why**: Redis Lists provide efficient push/pop operations with O(1) time complexity, making them ideal for message queues
|
||||
- **Alternatives considered**:
|
||||
- Redis Streams: More advanced but overkill for our use case
|
||||
- Redis Pub/Sub: No persistence, so commands would be lost if the receiving program is down
|
||||
|
||||
### Decision: Command History Storage
|
||||
- **What**: Store command history in memory with a configurable maximum size
|
||||
- **Why**: In-memory storage provides fast access times and avoids the complexity of database management
|
||||
- **Alternatives considered**:
|
||||
- Database storage: Adds complexity and latency
|
||||
- File system: Not suitable for real-time access
|
||||
|
||||
### Decision: Command Validation
|
||||
- **What**: Implement basic command validation on both frontend and backend
|
||||
- **Why**: Frontend validation provides immediate feedback to users, while backend validation ensures data integrity
|
||||
- **Alternatives considered**:
|
||||
- Only frontend validation: Less secure, as users could bypass it
|
||||
- Only backend validation: Less responsive, as users would have to wait for server response
|
||||
|
||||
## Architecture
|
||||
|
||||
### Frontend Architecture
|
||||
```
|
||||
CommandView Component
|
||||
├── CommandForm Component
|
||||
├── CommandHistory Component
|
||||
└── CommandService
|
||||
```
|
||||
|
||||
### Backend Architecture
|
||||
```
|
||||
Command Routes
|
||||
├── Command Service
|
||||
│ ├── Redis Client
|
||||
│ └── Command Manager
|
||||
└── Command History Manager
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Redis Connection
|
||||
- Use the `redis` npm package to connect to Redis
|
||||
- Implement automatic reconnection with exponential backoff
|
||||
- Handle connection errors gracefully
|
||||
|
||||
### Command Sending
|
||||
1. User enters a command in the frontend form
|
||||
2. Frontend validates the command (not empty, no invalid characters)
|
||||
3. Frontend sends a POST request to `/api/commands` with the command content
|
||||
4. Backend validates the command again
|
||||
5. Backend generates a unique command ID
|
||||
6. Backend adds the command to the Redis queue using `LPUSH`
|
||||
7. Backend stores the command in the in-memory command history
|
||||
8. Backend sends a success response to the frontend
|
||||
|
||||
### Command Validation
|
||||
- **Frontend validation**:
|
||||
- Check that the command is not empty
|
||||
- Check that the command does not contain invalid characters (e.g., null bytes)
|
||||
- Limit command length to 1024 characters
|
||||
- **Backend validation**:
|
||||
- Same checks as frontend
|
||||
- Additional server-side validation if needed
|
||||
|
||||
### Command History
|
||||
- Store command history in an array in memory
|
||||
- Implement a circular buffer to limit memory usage
|
||||
- Default maximum command count: 1000
|
||||
- Configurable via environment variable
|
||||
- Include command ID, content, timestamp, and status
|
||||
|
||||
### Command Response Handling
|
||||
1. Receiving program reads the command from the Redis queue
|
||||
2. Receiving program executes the command
|
||||
3. Receiving program writes the response to a separate Redis queue
|
||||
4. Backend listens for responses on the response queue using `BLPOP`
|
||||
5. When a response is received, backend updates the command status in the history
|
||||
6. Backend notifies the frontend of the response via Server-Sent Events (SSE)
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk: Redis Connection Failure
|
||||
- **Risk**: If Redis connection is lost, commands won't be sent
|
||||
- **Mitigation**: Implement automatic reconnection with exponential backoff, and notify users when connection is lost
|
||||
|
||||
### Risk: Command Loss
|
||||
- **Risk**: Commands could be lost if Redis goes down
|
||||
- **Mitigation**: Implement Redis persistence (RDB or AOF) to ensure commands are not lost
|
||||
|
||||
### Risk: Command Response Timeout
|
||||
- **Risk**: Commands could take too long to execute, causing the UI to hang
|
||||
- **Mitigation**: Implement a timeout mechanism for command responses, and show a loading indicator to users
|
||||
|
||||
## Migration Plan
|
||||
No migration is required as this is a new feature.
|
||||
|
||||
## Open Questions
|
||||
- What is the expected maximum command frequency per minute?
|
||||
- Should we add support for command templates or macros?
|
||||
- Should we implement command scheduling for future execution?
|
||||
97
openspec/specs/command/spec.md
Normal file
97
openspec/specs/command/spec.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Command Capability Specification
|
||||
|
||||
## Overview
|
||||
This specification defines the command capability for the BLS Project Console, which allows users to send console commands to Redis queues for other programs to read and execute.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Command Sending to Redis
|
||||
The system SHALL send commands to a Redis queue.
|
||||
|
||||
#### Scenario: Sending a command to Redis queue
|
||||
- **WHEN** the user enters a command in the console
|
||||
- **AND** clicks the "Send" button
|
||||
- **THEN** the command SHALL be sent to the Redis queue
|
||||
- **AND** the user SHALL receive a success confirmation
|
||||
|
||||
### Requirement: Command Validation
|
||||
The system SHALL validate commands before sending them to Redis.
|
||||
|
||||
#### Scenario: Validating an empty command
|
||||
- **WHEN** the user tries to send an empty command
|
||||
- **THEN** the system SHALL display an error message
|
||||
- **AND** the command SHALL NOT be sent to Redis
|
||||
|
||||
#### Scenario: Validating a command with invalid characters
|
||||
- **WHEN** the user tries to send a command with invalid characters
|
||||
- **THEN** the system SHALL display an error message
|
||||
- **AND** the command SHALL NOT be sent to Redis
|
||||
|
||||
### Requirement: Command History
|
||||
The system SHALL maintain a history of sent commands.
|
||||
|
||||
#### Scenario: Viewing command history
|
||||
- **WHEN** the user opens the command history
|
||||
- **THEN** the system SHALL display a list of previously sent commands
|
||||
- **AND** the user SHALL be able to select a command from the history to resend
|
||||
|
||||
### Requirement: Command Response Handling
|
||||
The system SHALL handle responses from commands sent to Redis.
|
||||
|
||||
#### Scenario: Receiving a command response
|
||||
- **WHEN** a command response is received from Redis
|
||||
- **THEN** the system SHALL display the response in the console
|
||||
- **AND** the response SHALL be associated with the original command
|
||||
|
||||
## Data Model
|
||||
|
||||
### Command
|
||||
```json
|
||||
{
|
||||
"id": "string",
|
||||
"content": "string",
|
||||
"timestamp": "ISO-8601 string",
|
||||
"status": "string" // e.g., sent, processing, completed, failed
|
||||
}
|
||||
```
|
||||
|
||||
### Command Response
|
||||
```json
|
||||
{
|
||||
"id": "string",
|
||||
"commandId": "string",
|
||||
"timestamp": "ISO-8601 string",
|
||||
"status": "string", // e.g., success, failure
|
||||
"result": "string" // command execution result
|
||||
}
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### POST /api/commands
|
||||
- **Description**: Send a command to the Redis queue
|
||||
- **Request Body**:
|
||||
```json
|
||||
{
|
||||
"content": "string" // the command to send
|
||||
}
|
||||
```
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Command sent successfully",
|
||||
"commandId": "string"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/commands/history
|
||||
- **Description**: Get command history
|
||||
- **Query Parameters**:
|
||||
- `limit`: Maximum number of commands to return (default: 50)
|
||||
- `offset`: Offset for pagination (default: 0)
|
||||
- **Response**: Array of command objects
|
||||
|
||||
### GET /api/commands/:id/response
|
||||
- **Description**: Get response for a specific command
|
||||
- **Response**: Command response object
|
||||
111
openspec/specs/logging/design.md
Normal file
111
openspec/specs/logging/design.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Logging Capability Design
|
||||
|
||||
## Context
|
||||
This design document describes the technical implementation of the logging capability for the BLS Project Console, which allows the system to read log records from Redis queues and display them in the console interface.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
### Goals
|
||||
- Implement real-time log reading from Redis queues
|
||||
- Provide a user-friendly log display interface
|
||||
- Support log filtering by level and time range
|
||||
- Ensure high performance and low latency
|
||||
- Implement proper error handling and reconnection mechanisms
|
||||
|
||||
### Non-Goals
|
||||
- Log storage or persistence beyond memory
|
||||
- Log analysis or visualization (charts, graphs)
|
||||
- Advanced log search capabilities
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision: Redis Queue Implementation
|
||||
- **What**: Use Redis List as the queue data structure
|
||||
- **Why**: Redis Lists provide efficient push/pop operations with O(1) time complexity, making them ideal for message queues
|
||||
- **Alternatives considered**:
|
||||
- Redis Streams: More advanced but overkill for our use case
|
||||
- Redis Pub/Sub: No persistence, so logs would be lost if the server is down
|
||||
|
||||
### Decision: Real-time Updates
|
||||
- **What**: Use Server-Sent Events (SSE) for real-time log updates
|
||||
- **Why**: SSE is simpler than WebSockets for one-way communication, has better browser support, and is easier to implement
|
||||
- **Alternatives considered**:
|
||||
- WebSockets: More complex for one-way communication
|
||||
- Polling: Higher latency and more resource-intensive
|
||||
|
||||
### Decision: Log Storage
|
||||
- **What**: Store logs in memory with a configurable maximum size
|
||||
- **Why**: In-memory storage provides fast access times and avoids the complexity of database management
|
||||
- **Alternatives considered**:
|
||||
- Database storage: Adds complexity and latency
|
||||
- File system: Not suitable for real-time access
|
||||
|
||||
## Architecture
|
||||
|
||||
### Frontend Architecture
|
||||
```
|
||||
LogView Component
|
||||
├── LogList Component
|
||||
├── LogFilter Component
|
||||
└── LogService
|
||||
```
|
||||
|
||||
### Backend Architecture
|
||||
```
|
||||
Log Routes
|
||||
├── Log Service
|
||||
│ ├── Redis Client
|
||||
│ └── Log Manager
|
||||
└── SSE Controller
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Redis Connection
|
||||
- Use the `redis` npm package to connect to Redis
|
||||
- Implement automatic reconnection with exponential backoff
|
||||
- Handle connection errors gracefully
|
||||
|
||||
### Log Reading
|
||||
1. Server establishes connection to Redis
|
||||
2. Server listens for new log records using `BLPOP` command (blocking pop)
|
||||
3. When a log record is received, it's added to the in-memory log store
|
||||
4. The log is then sent to all connected SSE clients
|
||||
|
||||
### Log Storage
|
||||
- Use an array to store log records in memory
|
||||
- Implement a circular buffer to limit memory usage
|
||||
- Default maximum log count: 10,000
|
||||
- Configurable via environment variable
|
||||
|
||||
### Log Display
|
||||
- Use a scrollable list to display logs
|
||||
- Implement virtual scrolling for large log sets to improve performance
|
||||
- Color-code logs by level (INFO: gray, WARN: yellow, ERROR: red, DEBUG: blue)
|
||||
|
||||
### Log Filtering
|
||||
- Implement client-side filtering for performance
|
||||
- Allow filtering by log level (INFO, WARN, ERROR, DEBUG)
|
||||
- Allow filtering by time range using a date picker
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk: Redis Connection Failure
|
||||
- **Risk**: If Redis connection is lost, logs won't be received
|
||||
- **Mitigation**: Implement automatic reconnection with exponential backoff, and notify users when connection is lost
|
||||
|
||||
### Risk: High Log Volume
|
||||
- **Risk**: Large number of logs could cause performance issues
|
||||
- **Mitigation**: Implement a circular buffer to limit memory usage, and use virtual scrolling in the frontend
|
||||
|
||||
### Risk: Browser Performance
|
||||
- **Risk**: Displaying thousands of logs could slow down the browser
|
||||
- **Mitigation**: Use virtual scrolling and limit the number of logs displayed at once
|
||||
|
||||
## Migration Plan
|
||||
No migration is required as this is a new feature.
|
||||
|
||||
## Open Questions
|
||||
- What is the expected maximum log volume per minute?
|
||||
- Should we add support for log persistence to disk?
|
||||
- Should we implement log search functionality?
|
||||
71
openspec/specs/logging/spec.md
Normal file
71
openspec/specs/logging/spec.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Logging Capability Specification
|
||||
|
||||
## Overview
|
||||
This specification defines the logging capability for the BLS Project Console, which allows the system to read log records from Redis queues and display them in the console interface.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Log Reading from Redis
|
||||
The system SHALL read log records from a Redis queue.
|
||||
|
||||
#### Scenario: Reading logs from Redis queue
|
||||
- **WHEN** the server starts
|
||||
- **THEN** it SHALL establish a connection to the Redis queue
|
||||
- **AND** it SHALL begin listening for new log records
|
||||
- **AND** it SHALL store log records in memory for display
|
||||
|
||||
### Requirement: Log Display in Console
|
||||
The system SHALL display log records in a user-friendly format.
|
||||
|
||||
#### Scenario: Displaying logs in the console
|
||||
- **WHEN** a log record is received from Redis
|
||||
- **THEN** it SHALL be added to the log list in the console
|
||||
- **AND** it SHALL display the log timestamp, level, and message
|
||||
- **AND** it SHALL support scrolling through historical logs
|
||||
|
||||
### Requirement: Log Filtering
|
||||
The system SHALL allow users to filter logs by level and time range.
|
||||
|
||||
#### Scenario: Filtering logs by level
|
||||
- **WHEN** the user selects a log level filter
|
||||
- **THEN** only logs with the selected level SHALL be displayed
|
||||
|
||||
#### Scenario: Filtering logs by time range
|
||||
- **WHEN** the user selects a time range
|
||||
- **THEN** only logs within the specified range SHALL be displayed
|
||||
|
||||
### Requirement: Log Auto-Refresh
|
||||
The system SHALL automatically refresh logs in real-time.
|
||||
|
||||
#### Scenario: Real-time log updates
|
||||
- **WHEN** a new log is added to the Redis queue
|
||||
- **THEN** it SHALL be automatically displayed in the console
|
||||
- **AND** the console SHALL scroll to the latest log if the user is viewing the end
|
||||
|
||||
## Data Model
|
||||
|
||||
### Log Record
|
||||
```json
|
||||
{
|
||||
"id": "string",
|
||||
"timestamp": "ISO-8601 string",
|
||||
"level": "string", // e.g., INFO, WARN, ERROR, DEBUG
|
||||
"message": "string",
|
||||
"metadata": "object" // optional additional data
|
||||
}
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### GET /api/logs
|
||||
- **Description**: Get log records
|
||||
- **Query Parameters**:
|
||||
- `level`: Filter logs by level
|
||||
- `startTime`: Filter logs from this timestamp
|
||||
- `endTime`: Filter logs up to this timestamp
|
||||
- `limit`: Maximum number of logs to return
|
||||
- **Response**: Array of log records
|
||||
|
||||
### GET /api/logs/live
|
||||
- **Description**: Establish a WebSocket connection for real-time log updates
|
||||
- **Response**: Continuous stream of log records
|
||||
114
openspec/specs/redis-connection/design.md
Normal file
114
openspec/specs/redis-connection/design.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Redis Connection Capability Design
|
||||
|
||||
## Context
|
||||
This design document describes the technical implementation of the Redis connection capability for the BLS Project Console, which manages the connection between the system and the Redis server for reading logs and sending commands.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
### Goals
|
||||
- Establish and manage connection to Redis server
|
||||
- Provide configuration options for Redis connection
|
||||
- Implement automatic reconnection mechanism
|
||||
- Handle connection errors gracefully
|
||||
- Monitor and report connection status
|
||||
|
||||
### Non-Goals
|
||||
- Redis server administration
|
||||
- Redis cluster management
|
||||
- Advanced Redis features (e.g., pub/sub, streams) beyond basic queue operations
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision: Redis Client Library
|
||||
- **What**: Use the official `redis` npm package
|
||||
- **Why**: It's the official Redis client for Node.js, well-maintained, and supports all Redis commands
|
||||
- **Alternatives considered**:
|
||||
- `ioredis`: More features but more complex
|
||||
- `node-redis`: Older, less maintained
|
||||
|
||||
### Decision: Connection Configuration
|
||||
- **What**: Use environment variables for Redis connection configuration
|
||||
- **Why**: Environment variables are a standard way to configure services in containerized environments, and they allow easy configuration without code changes
|
||||
- **Alternatives considered**:
|
||||
- Configuration files: Less flexible for containerized environments
|
||||
- Hardcoded values: Not suitable for production use
|
||||
|
||||
### Decision: Reconnection Strategy
|
||||
- **What**: Use exponential backoff for reconnection attempts
|
||||
- **Why**: Exponential backoff prevents overwhelming the Redis server with reconnection attempts, while still ensuring timely reconnection
|
||||
- **Alternatives considered**:
|
||||
- Fixed interval reconnection: Less efficient, could overwhelm the server
|
||||
- No reconnection: Not suitable for production use
|
||||
|
||||
## Architecture
|
||||
|
||||
### Redis Connection Architecture
|
||||
```
|
||||
Redis Connection Manager
|
||||
├── Redis Client
|
||||
├── Connection Monitor
|
||||
├── Reconnection Handler
|
||||
└── Configuration Manager
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Redis Client Initialization
|
||||
1. Server reads Redis configuration from environment variables
|
||||
2. Server creates a Redis client instance with the configuration
|
||||
3. Server attaches event listeners for connection events (connect, error, end, reconnecting)
|
||||
4. Server attempts to connect to Redis
|
||||
|
||||
### Configuration Parameters
|
||||
| Parameter | Default Value | Environment Variable | Description |
|
||||
|-----------|---------------|----------------------|-------------|
|
||||
| host | localhost | REDIS_HOST | Redis server hostname |
|
||||
| port | 6379 | REDIS_PORT | Redis server port |
|
||||
| password | null | REDIS_PASSWORD | Redis server password |
|
||||
| db | 0 | REDIS_DB | Redis database index |
|
||||
| connectTimeout | 10000 | REDIS_CONNECT_TIMEOUT | Connection timeout in milliseconds |
|
||||
| maxRetriesPerRequest | 3 | REDIS_MAX_RETRIES | Maximum retries per request |
|
||||
| reconnectStrategy | exponential | REDIS_RECONNECT_STRATEGY | Reconnection strategy (exponential, fixed) |
|
||||
| reconnectInterval | 1000 | REDIS_RECONNECT_INTERVAL | Base reconnection interval in milliseconds |
|
||||
| maxReconnectInterval | 30000 | REDIS_MAX_RECONNECT_INTERVAL | Maximum reconnection interval in milliseconds |
|
||||
|
||||
### Reconnection Implementation
|
||||
- Use the built-in reconnection feature of the `redis` package
|
||||
- Configure exponential backoff with:
|
||||
- Initial delay: 1 second
|
||||
- Maximum delay: 30 seconds
|
||||
- Factor: 1.5
|
||||
- Log each reconnection attempt with timestamp and delay
|
||||
|
||||
### Error Handling
|
||||
- **Connection errors**: Log the error, update connection status, and attempt to reconnect
|
||||
- **Command errors**: Log the error, update the command status, and notify the user
|
||||
- **Timeout errors**: Log the error, update connection status, and attempt to reconnect
|
||||
|
||||
### Connection Monitoring
|
||||
- Track connection status (connecting, connected, disconnected, error)
|
||||
- Log status changes with timestamps
|
||||
- Expose connection status via API endpoint
|
||||
- Update UI with connection status changes via Server-Sent Events (SSE)
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk: Redis Server Unavailability
|
||||
- **Risk**: If the Redis server is unavailable for an extended period, the system won't be able to read logs or send commands
|
||||
- **Mitigation**: Implement proper error handling and reconnection logic, and notify users of the issue
|
||||
|
||||
### Risk: Misconfiguration of Redis Connection
|
||||
- **Risk**: Incorrect Redis configuration could lead to connection failures
|
||||
- **Mitigation**: Validate configuration on startup, log configuration values (excluding passwords), and provide clear error messages
|
||||
|
||||
### Risk: Performance Impact of Reconnection Attempts
|
||||
- **Risk**: Frequent reconnection attempts could impact system performance
|
||||
- **Mitigation**: Use exponential backoff to reduce the frequency of reconnection attempts, and limit the maximum reconnection delay
|
||||
|
||||
## Migration Plan
|
||||
No migration is required as this is a new feature.
|
||||
|
||||
## Open Questions
|
||||
- What is the expected Redis server availability?
|
||||
- Should we implement connection pooling for better performance?
|
||||
- Should we support Redis Sentinel or Cluster for high availability?
|
||||
99
openspec/specs/redis-connection/spec.md
Normal file
99
openspec/specs/redis-connection/spec.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Redis Connection Capability Specification
|
||||
|
||||
## Overview
|
||||
This specification defines the Redis connection capability for the BLS Project Console, which manages the connection between the system and the Redis server for reading logs and sending commands.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Redis Connection Establishment
|
||||
The system SHALL establish a connection to the Redis server.
|
||||
|
||||
#### Scenario: Establishing Redis connection on server start
|
||||
- **WHEN** the server starts
|
||||
- **THEN** it SHALL attempt to connect to the Redis server
|
||||
- **AND** it SHALL log the connection status
|
||||
|
||||
### Requirement: Redis Connection Configuration
|
||||
The system SHALL allow configuration of Redis connection parameters.
|
||||
|
||||
#### Scenario: Configuring Redis connection via environment variables
|
||||
- **WHEN** the server starts with Redis environment variables set
|
||||
- **THEN** it SHALL use those variables to configure the Redis connection
|
||||
- **AND** it SHALL override default values
|
||||
|
||||
### Requirement: Redis Connection Reconnection
|
||||
The system SHALL automatically reconnect to Redis if the connection is lost.
|
||||
|
||||
#### Scenario: Reconnecting to Redis after connection loss
|
||||
- **WHEN** the Redis connection is lost
|
||||
- **THEN** the system SHALL attempt to reconnect with exponential backoff
|
||||
- **AND** it SHALL log each reconnection attempt
|
||||
- **AND** it SHALL notify the user when connection is restored
|
||||
|
||||
### Requirement: Redis Connection Error Handling
|
||||
The system SHALL handle Redis connection errors gracefully.
|
||||
|
||||
#### Scenario: Handling Redis connection failure
|
||||
- **WHEN** the system fails to connect to Redis
|
||||
- **THEN** it SHALL log the error
|
||||
- **AND** it SHALL display an error message to the user
|
||||
- **AND** it SHALL continue attempting to reconnect
|
||||
|
||||
### Requirement: Redis Connection Monitoring
|
||||
The system SHALL monitor the Redis connection status.
|
||||
|
||||
#### Scenario: Monitoring Redis connection status
|
||||
- **WHEN** the Redis connection status changes
|
||||
- **THEN** the system SHALL update the connection status in the UI
|
||||
- **AND** it SHALL log the status change
|
||||
|
||||
## Data Model
|
||||
|
||||
### Redis Connection Configuration
|
||||
```json
|
||||
{
|
||||
"host": "string",
|
||||
"port": "number",
|
||||
"password": "string",
|
||||
"db": "number",
|
||||
"socket": {
|
||||
"reconnectStrategy": "function",
|
||||
"connectTimeout": "number",
|
||||
"keepAlive": "number"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Redis Connection Status
|
||||
```json
|
||||
{
|
||||
"status": "string", // e.g., connecting, connected, disconnected, error
|
||||
"lastConnectedAt": "ISO-8601 string",
|
||||
"lastDisconnectedAt": "ISO-8601 string",
|
||||
"error": "string" // optional error message
|
||||
}
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### GET /api/redis/status
|
||||
- **Description**: Get Redis connection status
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"status": "string",
|
||||
"lastConnectedAt": "ISO-8601 string",
|
||||
"lastDisconnectedAt": "ISO-8601 string",
|
||||
"error": "string" // optional
|
||||
}
|
||||
```
|
||||
|
||||
### POST /api/redis/reconnect
|
||||
- **Description**: Manually reconnect to Redis
|
||||
- **Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Reconnection attempt initiated"
|
||||
}
|
||||
```
|
||||
3951
package-lock.json
generated
Normal file
3951
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
package.json
Normal file
31
package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "web-bls-projectconsole",
|
||||
"version": "1.0.0",
|
||||
"description": "前后端Node.js控制台项目,用于从Redis队列读取日志记录并展示,以及发送控制台指令到Redis队列",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"start": "node src/backend/server.js",
|
||||
"start:dev": "nodemon src/backend/server.js",
|
||||
"lint": "eslint . --ext .js,.vue",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.18.2",
|
||||
"redis": "^4.6.10",
|
||||
"vue": "^3.3.8",
|
||||
"vue-router": "^4.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.5.0",
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-plugin-vue": "^9.18.1",
|
||||
"nodemon": "^3.0.1",
|
||||
"prettier": "^3.1.0",
|
||||
"vite": "^5.0.0"
|
||||
}
|
||||
}
|
||||
12
public/index.html
Normal file
12
public/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BLS Project Console</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/frontend/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
22
src/backend/routes/commands.js
Normal file
22
src/backend/routes/commands.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import express from 'express'
|
||||
const router = express.Router()
|
||||
|
||||
// 发送指令
|
||||
router.post('/', (req, res) => {
|
||||
const { command } = req.body
|
||||
|
||||
if (!command) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '指令内容不能为空'
|
||||
})
|
||||
}
|
||||
|
||||
// 这里将实现发送指令到Redis队列的逻辑
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: '指令已发送到Redis队列'
|
||||
})
|
||||
})
|
||||
|
||||
export default router
|
||||
12
src/backend/routes/logs.js
Normal file
12
src/backend/routes/logs.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import express from 'express'
|
||||
const router = express.Router()
|
||||
|
||||
// 获取日志列表
|
||||
router.get('/', (req, res) => {
|
||||
// 这里将实现从Redis读取日志的逻辑
|
||||
res.status(200).json({
|
||||
logs: []
|
||||
})
|
||||
})
|
||||
|
||||
export default router
|
||||
25
src/backend/server.js
Normal file
25
src/backend/server.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import express from 'express'
|
||||
import cors from 'cors'
|
||||
import logRoutes from './routes/logs.js'
|
||||
import commandRoutes from './routes/commands.js'
|
||||
|
||||
const app = express()
|
||||
const PORT = 3001
|
||||
|
||||
// 中间件
|
||||
app.use(cors())
|
||||
app.use(express.json())
|
||||
|
||||
// 路由
|
||||
app.use('/api/logs', logRoutes)
|
||||
app.use('/api/commands', commandRoutes)
|
||||
|
||||
// 健康检查
|
||||
app.get('/api/health', (req, res) => {
|
||||
res.status(200).json({ status: 'ok' })
|
||||
})
|
||||
|
||||
// 启动服务器
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server running on port ${PORT}`)
|
||||
})
|
||||
43
src/frontend/App.vue
Normal file
43
src/frontend/App.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<header class="app-header">
|
||||
<h1>BLS Project Console</h1>
|
||||
</header>
|
||||
<main class="app-main">
|
||||
<router-view />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.app-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.app-header {
|
||||
background-color: #4285f4;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.app-main {
|
||||
flex: 1;
|
||||
padding: 1rem;
|
||||
}
|
||||
</style>
|
||||
7
src/frontend/main.js
Normal file
7
src/frontend/main.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(router)
|
||||
app.mount('#app')
|
||||
23
src/frontend/router/index.js
Normal file
23
src/frontend/router/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import LogView from '../views/LogView.vue'
|
||||
import CommandView from '../views/CommandView.vue'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'logs',
|
||||
component: LogView
|
||||
},
|
||||
{
|
||||
path: '/commands',
|
||||
name: 'commands',
|
||||
component: CommandView
|
||||
}
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
||||
154
src/frontend/views/CommandView.vue
Normal file
154
src/frontend/views/CommandView.vue
Normal file
@@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<div class="command-view">
|
||||
<h2>发送指令</h2>
|
||||
<form @submit.prevent="sendCommand" class="command-form">
|
||||
<div class="form-group">
|
||||
<label for="command">指令内容</label>
|
||||
<textarea
|
||||
id="command"
|
||||
v-model="command"
|
||||
rows="5"
|
||||
placeholder="请输入要发送的指令..."
|
||||
required
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">发送指令</button>
|
||||
<button type="button" class="btn btn-secondary" @click="clearCommand">清空</button>
|
||||
</div>
|
||||
</form>
|
||||
<div v-if="response" class="response-section">
|
||||
<h3>发送结果</h3>
|
||||
<div class="response-content" :class="{ 'success': response.success, 'error': !response.success }">
|
||||
{{ response.message }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const command = ref('')
|
||||
const response = ref(null)
|
||||
|
||||
const sendCommand = () => {
|
||||
// 这里将实现发送指令的逻辑
|
||||
response.value = {
|
||||
success: true,
|
||||
message: `指令已发送: ${command.value}`
|
||||
}
|
||||
command.value = ''
|
||||
}
|
||||
|
||||
const clearCommand = () => {
|
||||
command.value = ''
|
||||
response.value = null
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.command-view {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 1rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.command-form {
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
resize: vertical;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
textarea:focus {
|
||||
outline: none;
|
||||
border-color: #4285f4;
|
||||
box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.2);
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #4285f4;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #3367d6;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.response-section {
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 1rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.response-content {
|
||||
padding: 1rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.response-content.success {
|
||||
background-color: #e8f5e8;
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.response-content.error {
|
||||
background-color: #ffebee;
|
||||
color: #c62828;
|
||||
}
|
||||
</style>
|
||||
82
src/frontend/views/LogView.vue
Normal file
82
src/frontend/views/LogView.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<div class="log-view">
|
||||
<h2>日志记录</h2>
|
||||
<div class="log-container">
|
||||
<div v-if="logs.length === 0" class="empty-state">
|
||||
<p>暂无日志记录</p>
|
||||
</div>
|
||||
<div v-for="(log, index) in logs" :key="index" class="log-item">
|
||||
<div class="log-header">
|
||||
<span class="log-timestamp">{{ log.timestamp }}</span>
|
||||
<span class="log-level">{{ log.level }}</span>
|
||||
</div>
|
||||
<div class="log-message">{{ log.message }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const logs = ref([])
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.log-view {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 1rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.log-container {
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
padding: 1rem;
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.log-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.log-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.log-timestamp {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.log-level {
|
||||
font-weight: bold;
|
||||
padding: 0.2rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.log-message {
|
||||
color: #333;
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
26
vite.config.js
Normal file
26
vite.config.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import { resolve } from 'path'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
root: 'src/frontend',
|
||||
build: {
|
||||
outDir: '../../dist',
|
||||
emptyOutDir: true
|
||||
},
|
||||
server: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:3001',
|
||||
changeOrigin: true
|
||||
}
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, 'src/frontend')
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user