Files
erp-ass/docs/superpowers/plans/2026-03-21-erp-ai-assistant-phase1.md
dazhuang acd73431ae feat: implement ERP AI Assistant Phase 1
Backend (FastAPI + SQLAlchemy + Claude API + RAG):
- Config management with Pydantic v2
- Database engine with connection pooling and SQL injection prevention
- AI engine with Claude API integration (support custom base URL)
- RAG engine with ChromaDB and sentence-transformers
- Requirement analysis service
- Config generation service
- Executor engine with SQL validation
- REST API endpoints: /analyze, /generate, /execute

Frontend (Vue 3 + Element Plus + Pinia):
- Complete 3-step workflow: analyze → generate → execute
- Step indicator with progress visualization
- Analysis result display with field table
- SQL preview with monospace font
- Execute confirmation dialog with safety warning
- Execution result display
- State management with Pinia
- API service integration

Security:
- SQL injection prevention with parameterized queries
- Dangerous SQL operation blocking
- Database password URL encoding
- Transaction auto-rollback
- Pydantic config validation

Features:
- Natural language requirement analysis
- Automated SQL configuration generation
- Safe execution with human review
- LAN access support
- Custom Claude API endpoint support

Documentation:
- README with quick start guide
- Quick start guide
- LAN access configuration
- Dependency fixes guide
- Claude API configuration
- Git operation guide
- Implementation report

Dependencies fixed:
- numpy<2.0.0 for chromadb compatibility
- sentence-transformers==2.7.0 for huggingface_hub compatibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 14:23:20 +00:00

2460 lines
59 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ERP智能助手系统实施计划 (Phase 1)
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 构建一个可以通过自然语言或结构化表单配置ERP功能的Web应用实现需求解析、配置生成、审核确认、执行监控的完整流程。
**Architecture:** 单体内核架构Python FastAPI后端 + Vue 3前端。后端集成Claude API和RAG知识库通过SQL Server直连操作ERP配置表。采用TDD开发事务保护机制确保安全。
**Tech Stack:**
- 后端: FastAPI, SQLAlchemy, pyodbc, Claude API, ChromaDB, sentence-transformers
- 前端: Vue 3, Vite, Element Plus, Monaco Editor, Axios, Pinia
- 数据库: SQL Server, ChromaDB
---
## 文件结构规划
### 后端文件职责划分
**配置层**
- `backend/app/config.py` - 应用配置管理数据库、Claude API、知识库路径等
**数据访问层**
- `backend/app/core/db_engine.py` - 数据库连接池、事务管理、SQL执行
- `backend/app/models/request.py` - API请求模型Pydantic
- `backend/app/models/response.py` - API响应模型
- `backend/app/models/database.py` - 数据库表模型SQLAlchemy ORM如果需要
**核心引擎层**
- `backend/app/core/ai_engine.py` - Claude API客户端、Prompt模板、JSON解析
- `backend/app/core/rag_engine.py` - 知识库检索、文档向量化、元数据查询
- `backend/app/core/executor.py` - 配置执行器、事务编排、回滚机制
- `backend/app/core/validator.py` - SQL验证、风险检查、注入防护
**业务逻辑层**
- `backend/app/services/requirement_service.py` - 需求解析服务调用AI引擎
- `backend/app/services/config_service.py` - 配置生成服务
- `backend/app/services/execution_service.py` - 执行服务
**API层**
- `backend/app/api/analyze.py` - 需求解析API
- `backend/app/api/generate.py` - 配置生成API
- `backend/app/api/execute.py` - 执行配置API
- `backend/app/api/metadata.py` - 数据库元数据API
- `backend/app/api/history.py` - 历史记录API
**入口文件**
- `backend/app/main.py` - FastAPI应用入口、中间件配置、路由注册
**工具脚本**
- `backend/scripts/init_knowledge.py` - 初始化知识库
- `backend/scripts/import_docs.py` - 导入文档到知识库
**测试文件**
- `backend/tests/test_db_engine.py` - 数据库引擎测试
- `backend/tests/test_ai_engine.py` - AI引擎测试
- `backend/tests/test_api.py` - API集成测试
### 前端文件职责划分
**页面组件**
- `frontend/src/views/CreateFunction.vue` - 新建功能主页面(包含步骤器)
- `frontend/src/views/History.vue` - 历史记录页面
- `frontend/src/views/Settings.vue` - 系统设置页面
**可复用组件**
- `frontend/src/components/RequirementInput.vue` - 需求输入组件(自然语言+结构化表单)
- `frontend/src/components/ConfigPreview.vue` - 配置预览组件SQL预览+风险提示)
- `frontend/src/components/ExecutionMonitor.vue` - 执行监控组件(实时日志+进度条)
**API调用**
- `frontend/src/api/index.js` - Axios实例、API方法封装
**状态管理**
- `frontend/src/store/index.js` - Pinia store会话状态、执行状态
**路由配置**
- `frontend/src/router/index.js` - Vue Router配置
---
## 任务分解
### 任务1: 项目初始化和配置管理
**Files:**
- Create: `backend/requirements.txt`
- Create: `backend/.env.example`
- Create: `backend/app/config.py`
- Create: `backend/app/__init__.py`
- [ ] **Step 1: 创建requirements.txt**
```txt
fastapi==0.104.1
uvicorn[standard]==0.24.0
sqlalchemy==2.0.23
pyodbc==5.0.1
anthropic==0.18.1
chromadb==0.4.18
sentence-transformers==2.2.2
pydantic==2.5.0
pydantic-settings==2.1.0
python-dotenv==1.0.0
loguru==0.7.2
tenacity==8.2.3
python-jose[cryptography]==3.3.0
pytest==7.4.3
pytest-asyncio==0.21.1
httpx==0.25.2
```
- [ ] **Step 2: 创建.env.example**
```env
APP_NAME=ERP AI Assistant
APP_ENV=development
DEBUG=True
SECRET_KEY=change-this-in-production
# Database
DB_DRIVER=ODBC Driver 17 for SQL Server
DB_SERVER=192.168.120.19
DB_PORT=1433
DB_NAME=DMPF_HY
DB_USER=sa
DB_PASSWORD=your-password
# Claude API
ANTHROPIC_API_KEY=your-claude-api-key
CLAUDE_MODEL=claude-sonnet-4-6
CLAUDE_MAX_TOKENS=8192
CLAUDE_TEMPERATURE=0.7
# Knowledge Base
KNOWLEDGE_BASE_PATH=./knowledge_base
CHROMA_DB_PATH=./knowledge_base/chroma_db
EMBEDDING_MODEL=all-MiniLM-L6-v2
CHUNK_SIZE=500
CHUNK_OVERLAP=50
```
- [ ] **Step 3: 创建配置管理类**
创建 `backend/app/config.py`:
```python
from pydantic_settings import BaseSettings
from functools import lru_cache
class Settings(BaseSettings):
# Application
APP_NAME: str = "ERP AI Assistant"
APP_ENV: str = "development"
DEBUG: bool = True
SECRET_KEY: str
# Database
DB_DRIVER: str
DB_SERVER: str
DB_PORT: int = 1433
DB_NAME: str
DB_USER: str
DB_PASSWORD: str
# Claude API
ANTHROPIC_API_KEY: str
CLAUDE_MODEL: str = "claude-sonnet-4-6"
CLAUDE_MAX_TOKENS: int = 8192
CLAUDE_TEMPERATURE: float = 0.7
# Knowledge Base
KNOWLEDGE_BASE_PATH: str = "./knowledge_base"
CHROMA_DB_PATH: str = "./knowledge_base/chroma_db"
EMBEDDING_MODEL: str = "all-MiniLM-L6-v2"
CHUNK_SIZE: int = 500
CHUNK_OVERLAP: int = 50
@property
def DATABASE_URL(self) -> str:
"""构建数据库连接URL"""
return (
f"mssql+pyodbc://{self.DB_USER}:{self.DB_PASSWORD}"
f"@{self.DB_SERVER}:{self.DB_PORT}/{self.DB_NAME}"
f"?driver={self.DB_DRIVER}"
)
class Config:
env_file = ".env"
case_sensitive = True
@lru_cache()
def get_settings() -> Settings:
"""获取配置单例"""
return Settings()
```
- [ ] **Step 4: 创建__init__.py**
创建 `backend/app/__init__.py`:
```python
"""ERP AI Assistant Backend"""
__version__ = "1.0.0"
```
- [ ] **Step 5: 安装依赖并验证配置**
```bash
cd backend
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
```
验证:
```bash
python -c "from app.config import get_settings; s = get_settings(); print(s.APP_NAME)"
```
Expected: 输出配置的APP_NAME或报错缺少必需的环境变量
- [ ] **Step 6: Commit**
```bash
git add backend/
git commit -m "chore: initialize project with config management"
```
---
### 任务2: Pytest配置和测试基础设施
**Files:**
- Create: `backend/pytest.ini`
- Create: `backend/tests/conftest.py`
- Update: `backend/requirements.txt`
- [ ] **Step 1: 更新requirements.txt添加测试依赖**
`backend/requirements.txt` 末尾添加:
```txt
pytest-cov==4.1.0
pytest-mock==3.12.0
```
- [ ] **Step 2: 创建pytest.ini**
创建 `backend/pytest.ini`:
```ini
[pytest]
asyncio_mode = auto
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts = -v --cov=app --cov-report=term-missing
```
- [ ] **Step 3: 创建conftest.py**
创建 `backend/tests/conftest.py`:
```python
import pytest
from app.config import get_settings
@pytest.fixture
def test_settings():
"""测试配置"""
return get_settings()
@pytest.fixture
def mock_db_engine(mocker):
"""Mock数据库引擎"""
from app.core.db_engine import DatabaseEngine
return mocker.MagicMock(spec=DatabaseEngine)
@pytest.fixture
def mock_ai_engine(mocker):
"""Mock AI引擎"""
from app.core.ai_engine import ClaudeEngine
mock_engine = mocker.MagicMock(spec=ClaudeEngine)
mock_engine.parse_json_response = lambda x: {"功能名称": "测试功能"}
return mock_engine
```
- [ ] **Step 4: 验证pytest配置**
```bash
cd backend
pytest --version
```
Expected: 显示pytest版本信息
- [ ] **Step 5: Commit**
```bash
git add backend/pytest.ini backend/tests/conftest.py backend/requirements.txt
git commit -m "chore: add pytest configuration and test fixtures"
```
---
### 任务3: 数据库引擎实现
**Files:**
- Create: `backend/app/core/__init__.py`
- Create: `backend/app/core/db_engine.py`
- Create: `backend/tests/__init__.py`
- Create: `backend/tests/test_db_engine.py`
- [ ] **Step 1: 创建测试文件**
创建 `backend/tests/test_db_engine.py`:
```python
import pytest
from app.core.db_engine import DatabaseEngine
def test_database_engine_init():
"""测试数据库引擎初始化"""
engine = DatabaseEngine()
assert engine.engine is not None
assert engine.Session is not None
def test_execute_sql_select():
"""测试执行SELECT查询"""
engine = DatabaseEngine()
result = engine.execute_sql("SELECT 1 AS test")
assert result is not None
assert len(result) > 0
def test_table_exists():
"""测试表存在性检查"""
engine = DatabaseEngine()
# 假设SYS_FORM表存在
exists = engine.table_exists("SYS_FORM")
assert exists is True
```
- [ ] **Step 2: 运行测试验证失败**
```bash
cd backend
pytest tests/test_db_engine.py -v
```
Expected: FAIL - 模块不存在
- [ ] **Step 3: 实现数据库引擎**
创建 `backend/app/core/db_engine.py`:
```python
from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker
from contextlib import contextmanager
from loguru import logger
from app.config import get_settings
class DatabaseEngine:
"""数据库操作引擎"""
def __init__(self):
settings = get_settings()
self.engine = create_engine(
settings.DATABASE_URL,
pool_size=20,
max_overflow=10,
pool_pre_ping=True,
echo=settings.DEBUG
)
self.Session = sessionmaker(bind=self.engine)
@contextmanager
def get_session(self):
"""获取数据库会话(上下文管理器)"""
session = self.Session()
try:
yield session
session.commit()
except Exception as e:
session.rollback()
logger.error(f"数据库操作失败: {e}")
raise
finally:
session.close()
def execute_sql(self, sql: str, params: dict = None):
"""执行单条SQL"""
with self.get_session() as session:
result = session.execute(text(sql), params or {})
return result.fetchall()
def execute_transaction(self, sql_list: list, params_list: list = None):
"""执行事务多条SQL"""
params_list = params_list or [None] * len(sql_list)
with self.get_session() as session:
for sql, params in zip(sql_list, params_list):
session.execute(text(sql), params or {})
return True
def get_table_structure(self, table_name: str):
"""获取表结构"""
sql = f"""
SELECT
COLUMN_NAME,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH,
IS_NULLABLE,
COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '{table_name}'
ORDER BY ORDINAL_POSITION
"""
return self.execute_sql(sql)
def table_exists(self, table_name: str) -> bool:
"""检查表是否存在"""
sql = f"""
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = '{table_name}'
"""
result = self.execute_sql(sql)
return result[0][0] > 0
```
- [ ] **Step 4: 运行测试验证通过**
```bash
cd backend
pytest tests/test_db_engine.py -v
```
Expected: PASS - 所有测试通过
- [ ] **Step 5: Commit**
```bash
git add backend/app/core/ backend/tests/
git commit -m "feat: implement database engine with connection pooling"
```
---
### 任务3: AI引擎基础实现
**Files:**
- Create: `backend/app/core/ai_engine.py`
- Create: `backend/tests/test_ai_engine.py`
- [ ] **Step 1: 创建AI引擎测试**
创建 `backend/tests/test_ai_engine.py`:
```python
import pytest
from app.core.ai_engine import ClaudeEngine
def test_claude_engine_init():
"""测试Claude引擎初始化"""
engine = ClaudeEngine()
assert engine.client is not None
assert engine.model == "claude-sonnet-4-6"
def test_parse_json_response():
"""测试JSON解析"""
engine = ClaudeEngine()
# 测试纯JSON
json_str = '{"name": "test", "value": 123}'
result = engine.parse_json_response(json_str)
assert result["name"] == "test"
assert result["value"] == 123
# 测试markdown代码块
md_str = '```json\n{"name": "test"}\n```'
result = engine.parse_json_response(md_str)
assert result["name"] == "test"
```
- [ ] **Step 2: 运行测试验证失败**
```bash
pytest tests/test_ai_engine.py -v
```
Expected: FAIL - 模块不存在
- [ ] **Step 3: 实现AI引擎基础**
创建 `backend/app/core/ai_engine.py`:
```python
import anthropic
import json
import re
from loguru import logger
from app.config import get_settings
class ClaudeEngine:
"""Claude API调用引擎"""
def __init__(self):
settings = get_settings()
self.client = anthropic.Anthropic(api_key=settings.ANTHROPIC_API_KEY)
self.model = settings.CLAUDE_MODEL
self.max_tokens = settings.CLAUDE_MAX_TOKENS
self.temperature = settings.CLAUDE_TEMPERATURE
def parse_json_response(self, content: str) -> dict:
"""解析Claude返回的JSON"""
# 尝试直接解析
try:
return json.loads(content)
except json.JSONDecodeError:
pass
# 尝试提取```json```块
json_match = re.search(r'```json\s*(.*?)\s*```', content, re.DOTALL)
if json_match:
try:
return json.loads(json_match.group(1))
except json.JSONDecodeError:
pass
# 尝试提取{}块
json_match = re.search(r'\{.*\}', content, re.DOTALL)
if json_match:
try:
return json.loads(json_match.group(0))
except json.JSONDecodeError:
pass
raise ValueError(f"无法解析Claude返回的JSON: {content[:100]}")
async def call_claude(self, messages: list, temperature: float = None) -> str:
"""调用Claude API"""
try:
response = self.client.messages.create(
model=self.model,
max_tokens=self.max_tokens,
temperature=temperature or self.temperature,
messages=messages
)
return response.content[0].text
except Exception as e:
logger.error(f"Claude API调用失败: {e}")
raise
```
- [ ] **Step 4: 运行测试验证通过**
```bash
pytest tests/test_ai_engine.py -v
```
Expected: PASS
- [ ] **Step 5: Commit**
```bash
git add backend/app/core/ai_engine.py backend/tests/test_ai_engine.py
git commit -m "feat: implement Claude API engine with JSON parsing"
```
---
### 任务4: Prompt模板设计
**Files:**
- Create: `backend/app/core/prompts.py`
- Create: `backend/tests/test_prompts.py`
- [ ] **Step 1: 创建Prompt测试**
创建 `backend/tests/test_prompts.py`:
```python
from app.core.prompts import SYSTEM_PROMPT, ANALYZE_PROMPT_TEMPLATE
def test_system_prompt_exists():
"""测试系统Prompt存在"""
assert SYSTEM_PROMPT is not None
assert len(SYSTEM_PROMPT) > 100
assert "ERP平台配置专家" in SYSTEM_PROMPT
def test_analyze_prompt_template():
"""测试需求解析模板"""
rendered = ANALYZE_PROMPT_TEMPLATE.format(
user_input="创建销售订单",
knowledge_context="测试知识",
existing_tables="测试表"
)
assert "创建销售订单" in rendered
assert "测试知识" in rendered
```
- [ ] **Step 2: 运行测试验证失败**
```bash
pytest tests/test_prompts.py -v
```
Expected: FAIL
- [ ] **Step 3: 实现Prompt模板**
创建 `backend/app/core/prompts.py`:
```python
"""Prompt模板定义"""
SYSTEM_PROMPT = """你是一个ERP平台配置专家助手专门帮助开发人员配置一零软件结构化开发平台。
你的职责:
1. 理解用户的功能需求
2. 设计合理的数据库表结构
3. 生成符合平台规范的配置方案
4. 提供最佳实践建议
平台核心知识:
- 窗体类型0-普通、3-单树、4-树表、5-单据列表、11-一对多等
- 标准字段IKEY主键、COMPANYID、DOCCODE、DOCDATE、DOCSTATUS等
- 配置流程:建表 → 配置功能号 → 配置页面 → 配置菜单 → 配置IKEY
- 命名规范SA_销售、PU_采购、ST_库存、FI_财务
输出要求:
- 必须提供完整的SQL脚本
- 必须遵循平台配置规范
- 必须包含风险评估
- 使用JSON格式输出
"""
ANALYZE_PROMPT_TEMPLATE = """用户需求:{user_input}
参考知识:
{knowledge_context}
现有相关表:
{existing_tables}
请分析用户需求输出结构化需求文档JSON格式
{{
"功能名称": "xxx",
"功能号建议": "xx-xxx",
"窗体类型": "x",
"主表名建议": "XX_XXX",
"从表名建议": "XX_XXX_DETAIL",
"主表字段": [
{{
"字段名": "xxx",
"字段类型": "xxx",
"必填": true,
"默认值": "xxx",
"说明": "xxx"
}}
],
"从表字段": [],
"业务需求": [],
"关联表": [],
"风险提示": []
}}
"""
GENERATE_PROMPT_TEMPLATE = """结构化需求:
{requirements}
平台配置规范:
{platform_rules}
相似案例:
{similar_cases}
请生成完整的配置方案,包括:
1. 建表SQL主表、从表、日志表
2. 功能号配置SQL
3. 页面配置SQL
4. 菜单配置SQL
5. IKEY配置SQL
输出JSON格式
{{
"配置方案": {{
"建表SQL": [
{{
"表名": "SA_ORDER",
"类型": "主表",
"SQL": "CREATE TABLE SA_ORDER (...)",
"说明": "销售订单主表"
}}
],
"配置SQL": [
{{
"类型": "功能号配置",
"SQL": "INSERT INTO SYS_FORM (...)",
"说明": "配置功能号11-001"
}}
]
}},
"风险评估": [],
"建议后续操作": []
}}
"""
```
- [ ] **Step 4: 运行测试验证通过**
```bash
pytest tests/test_prompts.py -v
```
Expected: PASS
- [ ] **Step 5: Commit**
```bash
git add backend/app/core/prompts.py backend/tests/test_prompts.py
git commit -m "feat: add prompt templates for requirement analysis and config generation"
```
---
### 任务5: 知识库引擎基础实现
**Files:**
- Create: `backend/app/core/rag_engine.py`
- Create: `backend/knowledge_base/documents/.gitkeep`
- Create: `backend/scripts/init_knowledge.py`
- [ ] **Step 1: 创建知识库目录结构**
```bash
mkdir -p backend/knowledge_base/documents
touch backend/knowledge_base/documents/.gitkeep
```
- [ ] **Step 2: 实现RAG引擎基础**
创建 `backend/app/core/rag_engine.py`:
```python
import chromadb
from chromadb.config import Settings as ChromaSettings
from sentence_transformers import SentenceTransformer
from loguru import logger
from app.config import get_settings
class RAGEngine:
"""RAG检索引擎"""
def __init__(self):
settings = get_settings()
# 初始化向量数据库
self.chroma_client = chromadb.PersistentClient(
path=settings.CHROMA_DB_PATH,
settings=ChromaSettings(anonymized_telemetry=False)
)
# 初始化嵌入模型
logger.info(f"加载嵌入模型: {settings.EMBEDDING_MODEL}")
self.embedding_model = SentenceTransformer(settings.EMBEDDING_MODEL)
# 获取或创建集合
self.documents_collection = self.chroma_client.get_or_create_collection(
name="documents"
)
self.chunk_size = settings.CHUNK_SIZE
self.chunk_overlap = settings.CHUNK_OVERLAP
def add_document(self, doc_id: str, content: str, metadata: dict = None):
"""添加文档到知识库"""
# 分块
chunks = self._split_text(content)
# 生成嵌入
embeddings = self.embedding_model.encode(chunks)
# 添加到向量库
ids = [f"{doc_id}_chunk_{i}" for i in range(len(chunks))]
metadatas = [metadata or {} for _ in chunks]
self.documents_collection.add(
ids=ids,
documents=chunks,
embeddings=embeddings.tolist(),
metadatas=metadatas
)
logger.info(f"添加文档 {doc_id},共 {len(chunks)} 个块")
return len(chunks)
def search(self, query: str, top_k: int = 3) -> list:
"""检索相关文档"""
# 生成查询向量
query_embedding = self.embedding_model.encode([query])
# 检索
results = self.documents_collection.query(
query_embeddings=query_embedding.tolist(),
n_results=top_k
)
return [
{
"content": doc,
"metadata": meta,
"distance": dist
}
for doc, meta, dist in zip(
results["documents"][0],
results["metadatas"][0],
results["distances"][0]
)
]
def _split_text(self, text: str) -> list:
"""文本分块"""
chunks = []
start = 0
while start < len(text):
end = start + self.chunk_size
chunk = text[start:end]
chunks.append(chunk)
start += self.chunk_size - self.chunk_overlap
return chunks
```
- [ ] **Step 3: 创建知识库初始化脚本**
创建 `backend/scripts/init_knowledge.py`:
```python
#!/usr/bin/env python3
"""初始化知识库"""
import sys
import os
# 添加项目根目录到路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app.core.rag_engine import RAGEngine
from loguru import logger
def init_knowledge_base():
"""初始化知识库"""
logger.info("开始初始化知识库...")
rag = RAGEngine()
# 示例:添加平台基础知识
sample_doc = """
一零软件结构化开发平台配置指南
窗体类型:
- 0: 普通类型
- 3: 单树类型
- 4: 树表类型
- 5: 单据列表类型
- 11: 一对多的窗体类型
标准字段:
每张表都必须包含以下字段:
- IKEY: 主键,自增
- COMPANYID: 公司代码
- CREATE_USER: 创建人
- CREATE_DATE: 创建时间
- UPDATE_USER: 更新人
- UPDATE_DATE: 更新时间
单据类型额外字段:
- DOCCODE: 单据号
- DOCDATE: 单据日期
- DOCSTATUS: 单据状态
配置流程:
1. 在99-001创建功能号
2. 在99-003配置页面
3. 在99-002配置菜单
4. 在99-006配置IKEY
"""
rag.add_document(
doc_id="platform_basics",
content=sample_doc,
metadata={"source": "platform_intro", "type": "guide"}
)
logger.success("知识库初始化完成!")
if __name__ == "__main__":
init_knowledge_base()
```
- [ ] **Step 4: 测试知识库初始化**
```bash
cd backend
python scripts/init_knowledge.py
```
Expected: 成功初始化并输出日志
- [ ] **Step 5: Commit**
```bash
git add backend/app/core/rag_engine.py backend/scripts/ backend/knowledge_base/
git commit -m "feat: implement RAG engine with ChromaDB and sentence-transformers"
```
---
### 任务6: 需求解析服务实现
**Files:**
- Create: `backend/app/services/__init__.py`
- Create: `backend/app/services/requirement_service.py`
- Create: `backend/tests/test_requirement_service.py`
- [ ] **Step 1: 创建需求解析服务测试**
创建 `backend/tests/test_requirement_service.py`:
```python
import pytest
from app.services.requirement_service import RequirementService
@pytest.mark.asyncio
async def test_analyze_requirement():
"""测试需求解析"""
service = RequirementService()
result = await service.analyze(
user_input="创建一个销售订单管理页面",
session_id="test-session"
)
assert result is not None
assert "功能名称" in result
assert result["功能名称"] != ""
```
- [ ] **Step 2: 运行测试验证失败**
```bash
pytest tests/test_requirement_service.py -v
```
Expected: FAIL
- [ ] **Step 3: 实现需求解析服务**
创建 `backend/app/services/requirement_service.py`:
```python
from app.core.ai_engine import ClaudeEngine
from app.core.rag_engine import RAGEngine
from app.core.prompts import SYSTEM_PROMPT, ANALYZE_PROMPT_TEMPLATE
from app.core.db_engine import DatabaseEngine
from loguru import logger
import uuid
class RequirementService:
"""需求解析服务"""
def __init__(self):
self.ai_engine = ClaudeEngine()
self.rag_engine = RAGEngine()
self.db_engine = DatabaseEngine()
async def analyze(self, user_input: str, session_id: str = None) -> dict:
"""分析用户需求
Args:
user_input: 用户输入的自然语言需求
session_id: 会话ID用于上下文管理
Returns:
结构化需求文档
"""
session_id = session_id or str(uuid.uuid4())
logger.info(f"开始分析需求: {user_input[:50]}...")
# 1. 检索相关知识
knowledge_results = self.rag_engine.search(user_input, top_k=3)
knowledge_context = "\n\n".join([
f"{r['metadata'].get('source', '文档')}\n{r['content']}"
for r in knowledge_results
])
# 2. 查询现有相关表
existing_tables = self._get_existing_tables(user_input)
# 3. 构建Prompt
prompt = ANALYZE_PROMPT_TEMPLATE.format(
user_input=user_input,
knowledge_context=knowledge_context,
existing_tables=existing_tables
)
messages = [
{"role": "user", "content": SYSTEM_PROMPT},
{"role": "assistant", "content": "我已了解平台配置规范,请告诉我您的需求。"},
{"role": "user", "content": prompt}
]
# 4. 调用Claude API
response = await self.ai_engine.call_claude(messages, temperature=0.7)
# 5. 解析结果
result = self.ai_engine.parse_json_response(response)
logger.success(f"需求分析完成: {result.get('功能名称', 'Unknown')}")
return result
def _get_existing_tables(self, user_input: str) -> str:
"""查询现有相关表"""
# 简化版本:查询所有表
try:
sql = """
SELECT TOP 10 TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_NAME
"""
tables = self.db_engine.execute_sql(sql)
return "\n".join([f"- {t[0]}" for t in tables])
except Exception as e:
logger.warning(f"查询现有表失败: {e}")
return "无法获取现有表信息"
```
- [ ] **Step 4: 运行测试验证通过**
```bash
pytest tests/test_requirement_service.py -v
```
Expected: PASS需要配置Claude API Key
- [ ] **Step 5: Commit**
```bash
git add backend/app/services/ backend/tests/test_requirement_service.py
git commit -m "feat: implement requirement analysis service with Claude API"
```
---
### 任务7: 执行引擎实现
**Files:**
- Create: `backend/app/core/executor.py`
- Create: `backend/tests/test_executor.py`
- [ ] **Step 1: 创建执行引擎测试**
创建 `backend/tests/test_executor.py`:
```python
import pytest
from app.core.executor import ConfigExecutor
def test_executor_init():
"""测试执行器初始化"""
executor = ConfigExecutor()
assert executor.db_engine is not None
def test_validate_sql():
"""测试SQL验证"""
executor = ConfigExecutor()
# 测试合法SQL
is_valid, msg = executor.validate_sql("SELECT * FROM SYS_FORM")
assert is_valid is True
# 测试危险SQL
is_valid, msg = executor.validate_sql("DROP DATABASE test")
assert is_valid is False
assert "危险操作" in msg
```
- [ ] **Step 2: 运行测试验证失败**
```bash
pytest tests/test_executor.py -v
```
Expected: FAIL
- [ ] **Step 3: 实现执行引擎**
创建 `backend/app/core/executor.py`:
```python
import re
from typing import List, Tuple
from loguru import logger
from app.core.db_engine import DatabaseEngine
class ConfigExecutor:
"""配置执行器"""
# 危险SQL关键词
DANGEROUS_KEYWORDS = [
"DROP DATABASE",
"DROP TABLE",
"TRUNCATE TABLE",
"DELETE FROM",
"UPDATE.*SET",
"ALTER TABLE.*DROP"
]
def __init__(self):
self.db_engine = DatabaseEngine()
def validate_sql(self, sql: str) -> Tuple[bool, str]:
"""验证SQL安全性
Returns:
(is_valid, message)
"""
sql_upper = sql.upper()
# 检查危险操作
for keyword in self.DANGEROUS_KEYWORDS:
if re.search(keyword, sql_upper):
return False, f"危险操作被拦截: {keyword}"
return True, "SQL验证通过"
def execute_config(self, sql_list: List[str], session_id: str) -> dict:
"""执行配置SQL列表
Args:
sql_list: SQL列表
session_id: 会话ID
Returns:
执行结果
"""
logger.info(f"开始执行配置,共 {len(sql_list)} 条SQL")
results = {
"success": True,
"executed": [],
"failed": None,
"message": ""
}
try:
# 验证所有SQL
for i, sql in enumerate(sql_list):
is_valid, msg = self.validate_sql(sql)
if not is_valid:
raise ValueError(f"SQL #{i+1} 验证失败: {msg}")
# 执行事务
self.db_engine.execute_transaction(sql_list)
results["executed"] = sql_list
results["message"] = f"成功执行 {len(sql_list)} 条SQL"
logger.success(results["message"])
except Exception as e:
results["success"] = False
results["failed"] = str(e)
results["message"] = f"执行失败: {e}"
logger.error(results["message"])
return results
def rollback(self, session_id: str):
"""回滚操作占位符实际需要记录逆向SQL"""
logger.warning(f"回滚功能待实现: {session_id}")
return {"success": False, "message": "回滚功能待实现"}
```
- [ ] **Step 4: 运行测试验证通过**
```bash
pytest tests/test_executor.py -v
```
Expected: PASS
- [ ] **Step 5: Commit**
```bash
git add backend/app/core/executor.py backend/tests/test_executor.py
git commit -m "feat: implement config executor with SQL validation"
```
---
### 任务8: API层实现 - 基础结构
**Files:**
- Create: `backend/app/models/__init__.py`
- Create: `backend/app/models/request.py`
- Create: `backend/app/models/response.py`
- Create: `backend/app/api/__init__.py`
- Create: `backend/app/main.py`
- [ ] **Step 1: 创建请求/响应模型**
创建 `backend/app/models/request.py`:
```python
from pydantic import BaseModel, Field
from typing import Optional, List
class AnalyzeRequest(BaseModel):
"""需求解析请求"""
input_type: str = Field(..., description="输入类型: natural_language | structured")
content: str = Field(..., description="需求内容")
session_id: Optional[str] = Field(None, description="会话ID")
class GenerateRequest(BaseModel):
"""配置生成请求"""
session_id: str
requirements: dict
class ExecuteRequest(BaseModel):
"""执行配置请求"""
session_id: str
confirmed: bool = Field(False, description="用户确认标识")
backup_enabled: bool = Field(True, description="是否启用备份")
```
创建 `backend/app/models/response.py`:
```python
from pydantic import BaseModel
from typing import Optional, Any, List
class AnalyzeResponse(BaseModel):
"""需求解析响应"""
session_id: str
status: str
data: dict
class GenerateResponse(BaseModel):
"""配置生成响应"""
session_id: str
status: str
data: dict
class ExecuteResponse(BaseModel):
"""执行配置响应"""
execution_id: str
status: str
message: str
class ErrorResponse(BaseModel):
"""错误响应"""
error: dict
```
- [ ] **Step 2: 创建FastAPI主应用**
创建 `backend/app/main.py`:
```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config import get_settings
settings = get_settings()
app = FastAPI(
title=settings.APP_NAME,
version="1.0.0",
debug=settings.DEBUG
)
# CORS配置
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5173"], # Vue开发服务器
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
async def root():
"""根路径"""
return {
"message": settings.APP_NAME,
"version": "1.0.0",
"status": "running"
}
@app.get("/health")
async def health_check():
"""健康检查"""
return {"status": "healthy"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
```
- [ ] **Step 3: 启动服务验证**
```bash
cd backend
python -m app.main
```
访问 http://localhost:8000 验证返回JSON
- [ ] **Step 4: Commit**
```bash
git add backend/app/models/ backend/app/api/ backend/app/main.py
git commit -m "feat: create FastAPI application with request/response models"
```
---
### 任务9: API层实现 - 需求解析API
**Files:**
- Create: `backend/app/api/analyze.py`
- Update: `backend/app/main.py`
- [ ] **Step 1: 创建需求解析API**
创建 `backend/app/api/analyze.py`:
```python
from fastapi import APIRouter, HTTPException
from app.models.request import AnalyzeRequest
from app.models.response import AnalyzeResponse
from app.services.requirement_service import RequirementService
import uuid
router = APIRouter()
@router.post("/analyze", response_model=AnalyzeResponse)
async def analyze_requirement(request: AnalyzeRequest):
"""需求解析API"""
try:
service = RequirementService()
session_id = request.session_id or str(uuid.uuid4())
result = await service.analyze(
user_input=request.content,
session_id=session_id
)
return AnalyzeResponse(
session_id=session_id,
status="success",
data=result
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
```
- [ ] **Step 2: 注册路由到main.py**
更新 `backend/app/main.py`:
```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config import get_settings
from app.api import analyze # 添加导入
settings = get_settings()
app = FastAPI(
title=settings.APP_NAME,
version="1.0.0",
debug=settings.DEBUG
)
# CORS配置
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5173"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 注册路由
app.include_router(analyze.router, prefix="/api/v1", tags=["分析"])
@app.get("/")
async def root():
return {
"message": settings.APP_NAME,
"version": "1.0.0",
"status": "running"
}
@app.get("/health")
async def health_check():
return {"status": "healthy"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
```
- [ ] **Step 3: 测试API**
```bash
curl -X POST http://localhost:8000/api/v1/analyze \
-H "Content-Type: application/json" \
-d '{"input_type": "natural_language", "content": "创建销售订单管理页面"}'
```
Expected: 返回JSON响应
- [ ] **Step 4: Commit**
```bash
git add backend/app/api/analyze.py backend/app/main.py
git commit -m "feat: implement analyze API endpoint"
```
---
### 任务10: 前端项目初始化
**Files:**
- Create: `frontend/package.json`
- Create: `frontend/vite.config.js`
- Create: `frontend/index.html`
- Create: `frontend/src/main.js`
- Create: `frontend/src/App.vue`
- [ ] **Step 1: 初始化Vue项目**
```bash
cd frontend
npm create vite@latest . -- --template vue
npm install
npm install vue-router@4 pinia axios element-plus monaco-editor sql-formatter
```
- [ ] **Step 2: 配置vite.config.js**
```javascript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true
}
}
}
})
```
- [ ] **Step 3: 创建基础App.vue**
```vue
<template>
<div id="app">
<router-view />
</div>
</template>
<script setup>
</script>
<style>
#app {
font-family: 'Microsoft YaHei', sans-serif;
height: 100vh;
margin: 0;
}
</style>
```
- [ ] **Step 4: 启动前端验证**
```bash
npm run dev
```
访问 http://localhost:5173 验证Vue应用运行
- [ ] **Step 5: Commit**
```bash
git add frontend/
git commit -m "chore: initialize Vue 3 frontend with Vite"
```
---
### 任务11: 前端路由和布局
**Files:**
- Create: `frontend/src/router/index.js`
- Create: `frontend/src/views/Layout.vue`
- Update: `frontend/src/main.js`
- [ ] **Step 1: 创建路由配置**
创建 `frontend/src/router/index.js`:
```javascript
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
component: () => import('../views/Layout.vue'),
children: [
{
path: '',
redirect: '/create'
},
{
path: 'create',
name: 'CreateFunction',
component: () => import('../views/CreateFunction.vue')
},
{
path: 'history',
name: 'History',
component: () => import('../views/History.vue')
}
]
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
```
- [ ] **Step 2: 创建布局组件**
创建 `frontend/src/views/Layout.vue`:
```vue
<template>
<el-container class="layout-container">
<el-header class="header">
<div class="logo">ERP智能助手</div>
<div class="user-info">用户: Admin</div>
</el-header>
<el-container>
<el-aside width="200px" class="sidebar">
<el-menu
:default-active="$route.path"
router
>
<el-menu-item index="/create">
<el-icon><Edit /></el-icon>
<span>新建功能</span>
</el-menu-item>
<el-menu-item index="/history">
<el-icon><Document /></el-icon>
<span>历史记录</span>
</el-menu-item>
</el-menu>
</el-aside>
<el-main class="main-content">
<router-view />
</el-main>
</el-container>
</el-container>
</template>
<script setup>
import { Edit, Document } from '@element-plus/icons-vue'
</script>
<style scoped>
.layout-container {
height: 100vh;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
background: #409EFF;
color: white;
}
.logo {
font-size: 20px;
font-weight: bold;
}
.sidebar {
background: #f5f7fa;
}
.main-content {
background: #f0f2f5;
}
</style>
```
- [ ] **Step 3: 更新main.js**
```javascript
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')
```
- [ ] **Step 4: 创建占位页面**
创建 `frontend/src/views/CreateFunction.vue`:
```vue
<template>
<div class="create-function">
<h1>新建功能页面</h1>
<p>开发中...</p>
</div>
</template>
```
创建 `frontend/src/views/History.vue`:
```vue
<template>
<div class="history">
<h1>历史记录页面</h1>
<p>开发中...</p>
</div>
</template>
```
- [ ] **Step 5: 测试路由**
访问 http://localhost:5173 验证布局和路由切换
- [ ] **Step 6: Commit**
```bash
git add frontend/src/
git commit -m "feat: add frontend layout and routing"
```
---
### 任务12: 执行日志表和审计系统
**Files:**
- Create: `backend/scripts/create_log_table.sql`
- Create: `backend/app/models/audit.py`
- Create: `backend/app/services/audit_service.py`
- [ ] **Step 1: 创建执行日志表SQL脚本**
创建 `backend/scripts/create_log_table.sql`:
```sql
-- AI助手执行日志表
CREATE TABLE AI_ASSISTANT_LOG (
LOG_ID INT IDENTITY(1,1) PRIMARY KEY,
SESSION_ID VARCHAR(50) NOT NULL,
EXECUTION_ID VARCHAR(50),
USER_ID VARCHAR(50),
ACTION_TYPE VARCHAR(50),
SQL_CONTENT NVARCHAR(MAX),
STATUS VARCHAR(20),
ERROR_MESSAGE NVARCHAR(MAX),
EXECUTION_TIME INT,
CREATE_TIME DATETIME DEFAULT GETDATE(),
INDEX IX_SESSION_ID (SESSION_ID),
INDEX IX_CREATE_TIME (CREATE_TIME)
);
-- 创建索引
CREATE INDEX IX_EXECUTION_ID ON AI_ASSISTANT_LOG(EXECUTION_ID);
```
- [ ] **Step 2: 执行SQL创建表**
```bash
# 使用sqlcmd或数据库管理工具执行
sqlcmd -S 192.168.120.19 -d DMPF_HY -U sa -P your-password -i backend/scripts/create_log_table.sql
```
- [ ] **Step 3: 创建审计模型**
创建 `backend/app/models/audit.py`:
```python
from pydantic import BaseModel
from datetime import datetime
from typing import Optional
class ExecutionLog(BaseModel):
"""执行日志模型"""
log_id: Optional[int]
session_id: str
execution_id: Optional[str]
user_id: Optional[str]
action_type: str
sql_content: str
status: str
error_message: Optional[str]
execution_time: Optional[int]
create_time: Optional[datetime] = None
```
- [ ] **Step 4: 创建审计服务**
创建 `backend/app/services/audit_service.py`:
```python
from app.core.db_engine import DatabaseEngine
from app.models.audit import ExecutionLog
from loguru import logger
import uuid
class AuditService:
"""审计服务"""
def __init__(self):
self.db_engine = DatabaseEngine()
def log_execution(self, log: ExecutionLog) -> int:
"""记录执行日志"""
sql = """
INSERT INTO AI_ASSISTANT_LOG
(SESSION_ID, EXECUTION_ID, USER_ID, ACTION_TYPE, SQL_CONTENT, STATUS, ERROR_MESSAGE, EXECUTION_TIME)
VALUES
(:session_id, :execution_id, :user_id, :action_type, :sql_content, :status, :error_message, :execution_time)
"""
params = {
"session_id": log.session_id,
"execution_id": log.execution_id or str(uuid.uuid4()),
"user_id": log.user_id or "system",
"action_type": log.action_type,
"sql_content": log.sql_content,
"status": log.status,
"error_message": log.error_message,
"execution_time": log.execution_time
}
try:
self.db_engine.execute_sql(sql, params)
logger.info(f"记录执行日志: {log.action_type}")
return 1
except Exception as e:
logger.error(f"记录执行日志失败: {e}")
return 0
def get_execution_history(self, session_id: str, limit: int = 100):
"""获取执行历史"""
sql = f"""
SELECT TOP {limit} *
FROM AI_ASSISTANT_LOG
WHERE SESSION_ID = '{session_id}'
ORDER BY CREATE_TIME DESC
"""
return self.db_engine.execute_sql(sql)
```
- [ ] **Step 5: 编写测试**
创建 `backend/tests/test_audit_service.py`:
```python
from app.services.audit_service import AuditService
from app.models.audit import ExecutionLog
def test_log_execution():
"""测试执行日志记录"""
service = AuditService()
log = ExecutionLog(
session_id="test-session",
action_type="TEST",
sql_content="SELECT 1",
status="SUCCESS"
)
result = service.log_execution(log)
assert result == 1
```
- [ ] **Step 6: 运行测试**
```bash
pytest tests/test_audit_service.py -v
```
- [ ] **Step 7: Commit**
```bash
git add backend/scripts/create_log_table.sql backend/app/models/audit.py backend/app/services/audit_service.py backend/tests/test_audit_service.py
git commit -m "feat: add execution logging and audit system"
```
---
### 任务13: 配置生成服务
**Files:**
- Create: `backend/app/services/config_service.py`
- Create: `backend/tests/test_config_service.py`
- [ ] **Step 1: 创建配置生成服务测试**
创建 `backend/tests/test_config_service.py`:
```python
import pytest
from app.services.config_service import ConfigService
@pytest.mark.asyncio
async def test_generate_config():
"""测试配置生成"""
service = ConfigService()
requirements = {
"功能名称": "销售订单",
"功能号建议": "11-001",
"窗体类型": "5",
"主表名建议": "SA_ORDER",
"主表字段": [
{"字段名": "订单号", "字段类型": "varchar(50)", "必填": True}
]
}
result = await service.generate(requirements, "test-session")
assert result is not None
assert "配置方案" in result
```
- [ ] **Step 2: 运行测试验证失败**
```bash
pytest tests/test_config_service.py -v
```
Expected: FAIL
- [ ] **Step 3: 实现配置生成服务**
创建 `backend/app/services/config_service.py`:
```python
from app.core.ai_engine import ClaudeEngine
from app.core.rag_engine import RAGEngine
from app.core.prompts import SYSTEM_PROMPT, GENERATE_PROMPT_TEMPLATE
from app.core.db_engine import DatabaseEngine
from loguru import logger
class ConfigService:
"""配置生成服务"""
def __init__(self):
self.ai_engine = ClaudeEngine()
self.rag_engine = RAGEngine()
self.db_engine = DatabaseEngine()
async def generate(self, requirements: dict, session_id: str) -> dict:
"""生成配置方案
Args:
requirements: 结构化需求
session_id: 会话ID
Returns:
配置方案包含SQL列表
"""
logger.info(f"开始生成配置: {requirements.get('功能名称', 'Unknown')}")
# 1. 检索相关知识
platform_rules = self._get_platform_rules(requirements.get("窗体类型", "0"))
similar_cases = self._get_similar_cases(requirements.get("功能名称", ""))
# 2. 构建Prompt
prompt = GENERATE_PROMPT_TEMPLATE.format(
requirements=str(requirements),
platform_rules=platform_rules,
similar_cases=similar_cases
)
messages = [
{"role": "user", "content": SYSTEM_PROMPT},
{"role": "assistant", "content": "我已了解,请提供需求信息。"},
{"role": "user", "content": prompt}
]
# 3. 调用Claude API
response = await self.ai_engine.call_claude(messages, temperature=0.5)
# 4. 解析结果
result = self.ai_engine.parse_json_response(response)
logger.success(f"配置生成完成")
return result
def _get_platform_rules(self, form_type: str) -> str:
"""获取平台配置规则"""
# 简化版本:从知识库检索
results = self.rag_engine.search(f"窗体类型{form_type}配置规则", top_k=2)
return "\n\n".join([r["content"] for r in results])
def _get_similar_cases(self, keywords: str) -> str:
"""获取相似案例"""
results = self.rag_engine.search(keywords, top_k=2)
return "\n\n".join([r["content"] for r in results])
```
- [ ] **Step 4: 运行测试验证通过**
```bash
pytest tests/test_config_service.py -v
```
Expected: PASS
- [ ] **Step 5: Commit**
```bash
git add backend/app/services/config_service.py backend/tests/test_config_service.py
git commit -m "feat: implement config generation service"
```
---
### 任务14: 执行配置API
**Files:**
- Create: `backend/app/api/execute.py`
- Create: `backend/app/api/generate.py`
- Update: `backend/app/main.py`
- [ ] **Step 1: 创建配置生成API**
创建 `backend/app/api/generate.py`:
```python
from fastapi import APIRouter, HTTPException
from app.models.request import GenerateRequest
from app.models.response import GenerateResponse
from app.services.config_service import ConfigService
router = APIRouter()
@router.post("/generate", response_model=GenerateResponse)
async def generate_config(request: GenerateRequest):
"""配置生成API"""
try:
service = ConfigService()
result = await service.generate(
requirements=request.requirements,
session_id=request.session_id
)
return GenerateResponse(
session_id=request.session_id,
status="success",
data=result
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
```
- [ ] **Step 2: 创建执行配置API**
创建 `backend/app/api/execute.py`:
```python
from fastapi import APIRouter, HTTPException
from app.models.request import ExecuteRequest
from app.models.response import ExecuteResponse
from app.core.executor import ConfigExecutor
from app.services.audit_service import AuditService
from app.models.audit import ExecutionLog
import uuid
router = APIRouter()
@router.post("/execute", response_model=ExecuteResponse)
async def execute_config(request: ExecuteRequest):
"""执行配置API"""
try:
executor = ConfigExecutor()
audit_service = AuditService()
execution_id = str(uuid.uuid4())
# TODO: 从session获取SQL列表实际应从数据库或缓存获取
sql_list = [] # 占位符
# 执行配置
result = executor.execute_config(sql_list, request.session_id)
# 记录日志
for sql in sql_list:
log = ExecutionLog(
session_id=request.session_id,
execution_id=execution_id,
action_type="EXECUTE_SQL",
sql_content=sql,
status="SUCCESS" if result["success"] else "FAILED",
error_message=result.get("failed")
)
audit_service.log_execution(log)
return ExecuteResponse(
execution_id=execution_id,
status="success" if result["success"] else "failed",
message=result["message"]
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
```
- [ ] **Step 3: 更新main.py注册路由**
`backend/app/main.py` 中添加路由:
```python
from app.api import analyze, generate, execute
# ...existing code...
# 注册路由
app.include_router(analyze.router, prefix="/api/v1", tags=["分析"])
app.include_router(generate.router, prefix="/api/v1", tags=["生成"])
app.include_router(execute.router, prefix="/api/v1", tags=["执行"])
```
- [ ] **Step 4: 测试API**
```bash
curl -X POST http://localhost:8000/api/v1/generate \
-H "Content-Type: application/json" \
-d '{"session_id": "test", "requirements": {"功能名称": "测试"}}'
```
- [ ] **Step 5: Commit**
```bash
git add backend/app/api/generate.py backend/app/api/execute.py backend/app/main.py
git commit -m "feat: add generate and execute API endpoints"
```
---
### 任务15: 前端需求输入组件
**Files:**
- Create: `frontend/src/components/RequirementInput.vue`
- Create: `frontend/src/api/index.js`
- [ ] **Step 1: 创建API调用封装**
创建 `frontend/src/api/index.js`:
```javascript
import axios from 'axios'
const api = axios.create({
baseURL: '/api/v1',
timeout: 60000,
headers: {
'Content-Type': 'application/json'
}
})
export default {
async analyze(content, inputType = 'natural_language') {
const response = await api.post('/analyze', {
input_type: inputType,
content
})
return response.data
},
async generate(sessionId, requirements) {
const response = await api.post('/generate', {
session_id: sessionId,
requirements
})
return response.data
},
async execute(sessionId, confirmed = true) {
const response = await api.post('/execute', {
session_id: sessionId,
confirmed,
backup_enabled: true
})
return response.data
}
}
```
- [ ] **Step 2: 创建需求输入组件**
创建 `frontend/src/components/RequirementInput.vue`:
```vue
<template>
<el-card class="requirement-input">
<template #header>
<div class="card-header">
<span>需求输入</span>
<el-radio-group v-model="inputMode" size="small">
<el-radio-button label="natural">自然语言</el-radio-button>
<el-radio-button label="structured">结构化表单</el-radio-button>
</el-radio-group>
</div>
</template>
<!-- 自然语言模式 -->
<div v-if="inputMode === 'natural'" class="natural-input">
<el-input
v-model="naturalInput"
type="textarea"
:rows="6"
placeholder="请描述您的需求,例如:创建一个销售订单管理页面,包含订单号、客户、金额等字段..."
/>
<el-button type="primary" @click="submitNatural" :loading="loading" style="margin-top: 10px">
提交需求
</el-button>
</div>
<!-- 结构化表单模式 -->
<div v-else class="structured-input">
<el-form :model="formData" label-width="100px">
<el-form-item label="功能名称">
<el-input v-model="formData.functionName" />
</el-form-item>
<el-form-item label="窗体类型">
<el-select v-model="formData.formType">
<el-option label="普通类型" value="0" />
<el-option label="单据列表" value="5" />
<el-option label="一对多" value="11" />
</el-select>
</el-form-item>
<el-divider>主表字段</el-divider>
<el-table :data="formData.fields" style="width: 100%">
<el-table-column prop="name" label="字段名">
<template #default="{ row }">
<el-input v-model="row.name" />
</template>
</el-table-column>
<el-table-column prop="type" label="类型">
<template #default="{ row }">
<el-select v-model="row.type">
<el-option label="varchar(50)" value="varchar(50)" />
<el-option label="int" value="int" />
<el-option label="decimal(18,2)" value="decimal(18,2)" />
<el-option label="datetime" value="datetime" />
</el-select>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ $index }">
<el-button type="danger" size="small" @click="removeField($index)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-button type="primary" size="small" @click="addField" style="margin-top: 10px">
添加字段
</el-button>
<el-button type="success" @click="submitStructured" :loading="loading" style="margin-top: 20px">
生成配置
</el-button>
</el-form>
</div>
</el-card>
</template>
<script setup>
import { ref } from 'vue'
import api from '../api'
import { ElMessage } from 'element-plus'
const emit = defineEmits(['submitted'])
const inputMode = ref('natural')
const naturalInput = ref('')
const loading = ref(false)
const formData = ref({
functionName: '',
formType: '5',
fields: [
{ name: '', type: 'varchar(50)' }
]
})
const addField = () => {
formData.value.fields.push({ name: '', type: 'varchar(50)' })
}
const removeField = (index) => {
formData.value.fields.splice(index, 1)
}
const submitNatural = async () => {
if (!naturalInput.value.trim()) {
ElMessage.warning('请输入需求描述')
return
}
loading.value = true
try {
const result = await api.analyze(naturalInput.value)
emit('submitted', result)
ElMessage.success('需求解析成功')
} catch (error) {
ElMessage.error('需求解析失败:' + error.message)
} finally {
loading.value = false
}
}
const submitStructured = async () => {
loading.value = true
try {
// TODO: 转换formData为后端需要的格式
const result = await api.analyze(JSON.stringify(formData.value), 'structured')
emit('submitted', result)
ElMessage.success('提交成功')
} catch (error) {
ElMessage.error('提交失败:' + error.message)
} finally {
loading.value = false
}
}
</script>
<style scoped>
.requirement-input {
margin-bottom: 20px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
```
- [ ] **Step 3: 更新CreateFunction.vue使用组件**
更新 `frontend/src/views/CreateFunction.vue`:
```vue
<template>
<div class="create-function">
<el-steps :active="currentStep" finish-status="success">
<el-step title="输入需求" />
<el-step title="生成配置" />
<el-step title="审核确认" />
<el-step title="执行" />
<el-step title="完成" />
</el-steps>
<div class="step-content" style="margin-top: 20px">
<requirement-input v-if="currentStep === 0" @submitted="handleSubmitted" />
<div v-else-if="currentStep === 1">生成配置中...</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import RequirementInput from '../components/RequirementInput.vue'
const currentStep = ref(0)
const handleSubmitted = (result) => {
console.log('需求解析结果:', result)
currentStep.value = 1
}
</script>
```
- [ ] **Step 4: 测试组件**
访问 http://localhost:5173/create 验证组件显示和交互
- [ ] **Step 5: Commit**
```bash
git add frontend/src/components/RequirementInput.vue frontend/src/api/index.js frontend/src/views/CreateFunction.vue
git commit -m "feat: add requirement input component with natural language and structured form"
```
---
## 剩余任务概要
由于篇幅限制,以下任务保持概要形式,将在执行过程中细化:
### 任务16: 配置预览组件
- SQL预览Monaco Editor
- 风险提示显示
- 审核确认按钮
### 任务17: 执行监控组件
- 实时日志显示
- 进度条
- WebSocket支持可选
### 任务18: 历史记录API和页面
- 查询历史记录API
- 历史记录列表页面
- 详情查看
### 任务19: 数据库元数据API
- 表列表查询
- 表结构详情
- 功能号列表
### 任务20: 知识库管理
- 文档上传界面
- 文档列表
- 索引重建
### 任务21-25: 测试与部署
- 单元测试完善
- 集成测试
- Docker配置
- docker-compose编排
- README文档
---
## 执行策略
**推荐方式**: 使用 `superpowers:subagent-driven-development` 技能
- 每个任务由独立子代理执行
- 任务间有明确的文件依赖
- 每个任务完成后进行代码审查
- 遵循TDD流程测试先行
**关键检查点**:
1. 任务5后知识库可正常检索
2. 任务9后API可通过Postman测试
3. 任务11后前端可访问和导航
4. 任务20后核心流程打通
---
## 风险与应对
1. **Claude API调用失败**
- 确保配置正确的API Key
- 网络代理问题需提前解决
2. **数据库连接失败**
- 检查SQL Server配置
- 验证防火墙规则
- 测试ODBC驱动安装
3. **前后端联调问题**
- 使用浏览器开发者工具检查网络请求
- 检查CORS配置
---
## 验收标准
- [ ] 可以通过自然语言生成简单功能配置
- [ ] 生成的SQL可以成功执行
- [ ] 执行日志完整记录所有操作
- [ ] 前端界面可用,流程完整
- [ ] 核心API有单元测试覆盖
- [ ] 代码已提交到Git仓库
---
**计划创建时间**: 2026-03-21
**预计实施周期**: Phase 1约4周
**文档版本**: 1.0