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>
2460 lines
59 KiB
Markdown
2460 lines
59 KiB
Markdown
# 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 |