feat: 实现完整三级标题生成功能

- 扩展DocumentChapter模型支持嵌套结构和评分值
- 新增智能分组算法,按关键词和前缀对评分项进行分类
- 重写章节生成逻辑,支持一级、二级、三级标题完整结构
- 优化显示系统,支持递归显示和颜色区分
- 增强表格解析能力,处理复杂的合并单元格结构
- 改进AI识别逻辑,更好地识别评分表格类型
- 完善.gitignore文件,添加项目相关忽略规则

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
sladro 2025-09-25 14:33:30 +08:00
parent 47fc26f3f0
commit f48971cf67
5 changed files with 385 additions and 51 deletions

59
.gitignore vendored
View File

@ -1,10 +1,63 @@
# Python-generated files
# Python
__pycache__/
*.py[oc]
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# Virtual environments
.venv
.env
venv/
ENV/
env.bak/
venv.bak/
# Testing
.pytest_cache/
.coverage
.hypothesis/
htmlcov/
# IDE
.vscode/
.idea/
*.swp
*.swo
# Claude Code
.claude/
# Project specific
data/kb/
*.docx
*.xlsx
*.csv
*.pdf
logs/
temp/
# OS
.DS_Store
Thumbs.db
# Ruff cache
.ruff_cache/

4
data/README.md Normal file
View File

@ -0,0 +1,4 @@
# 数据存储目录
- kb/: 知识库数据(向量数据库)
- projects/: 项目数据存储

View File

@ -0,0 +1,128 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## 项目概述
这是一个基于Three.js的3D模型查看器和船厂三维数据管理展示系统。项目包含两个主要页面
- `index.html`: 主要的3D模型查看器界面支持模型加载、选择、测量、标注等功能
- `1.html`: 船舶建造精度数字化平台的数据分析界面通过iframe嵌入3D查看器
## 技术架构
### 前端技术栈
- **Three.js**: 核心3D渲染引擎
- **原生JavaScript**: ES6+ 模块化架构,无框架依赖
- **HTML5/CSS3**: 响应式布局使用Flexbox和Grid
- **Tailwind CSS**: 样式框架仅在1.html中使用
- **ECharts**: 数据可视化图表仅在1.html中使用
### 核心模块结构
所有JavaScript模块位于 `js/` 目录下,采用模块化设计:
#### 核心管理器
- **ModelViewer** (`main.js`): 主应用入口管理整个3D场景
- **ModelManager** (`ModelManager.js`): 模型管理,处理模型的加载和切换
- **ModelLoader** (`ModelLoader.js`): 模型加载器支持GLTF格式
- **ModelAPI** (`ModelAPI.js`): 模型API接口提供程序化控制
#### 功能管理器
- **SelectionManager** (`SelectionManager.js`): 零件选择和高亮
- **MeasurementManager** (`MeasurementManager.js`): 3D测量工具距离、角度、面积
- **ClippingManager** (`ClippingManager.js`): 切面控制
- **AnnotationManager** (`AnnotationManager.js`): 3D标注功能
- **ModelTreeManager** (`ModelTreeManager.js`): 模型结构树管理
- **AnomalyDisplayManager** (`AnomalyDisplayManager.js`): 异常状态显示
- **LayerDisplayManager** (`LayerDisplayManager.js`): 分层显示管理
#### UI和状态管理
- **UIController** (`UIController.js`): UI控制器管理所有界面交互
- **ObjectStateManager** (`ObjectStateManager.js`): 对象状态管理
- **StorageManager** (`StorageManager.js`): 本地存储管理
- **OutlineManager** (`OutlineManager.js`): 边缘高亮效果
### 资源结构
- **models/**: 3D模型文件.glb格式
- **css/**: 样式文件主要是style.css
- **image/**: UI图标和图片资源
- **three/**: Three.js库文件
## 开发环境
### 启动开发服务器
由于项目使用ES6模块和本地文件引用需要通过HTTP服务器运行
```bash
# 使用Live Server推荐
# VS Code安装Live Server扩展配置端口5501
# 右键点击index.html选择"Open with Live Server"
# 或使用Python内置服务器
python -m http.server 5501
# 或使用Node.js http-server
npx http-server -p 5501
```
### 访问页面
- 3D模型查看器: `http://localhost:5501/index.html`
- 数据分析平台: `http://localhost:5501/1.html`
## 开发约定
### 模型文件管理
- 支持的格式: .glb (推荐)
- 模型文件存放在 `models/` 目录
- 默认加载模型: `CX0856_CB01C.glb`
### 配置和状态管理
- 使用 `StorageManager` 进行本地存储
- 配置项通过 `ObjectStateManager` 管理
- 模型状态通过事件系统同步
### 代码风格
- 使用ES6+语法和模块
- 采用面向对象设计模式
- 每个功能模块独立文件
- 使用驼峰命名法
- 保持代码注释的完整性
### 事件通信
项目使用自定义事件系统进行模块间通信:
- 模型加载完成事件
- 选择状态变化事件
- UI状态更新事件
- 测量结果事件
### 浏览器兼容性
- 支持现代浏览器Chrome 88+, Firefox 85+, Safari 14+
- 依赖ES6模块支持
- 需要WebGL 2.0支持
## 调试和测试
### 控制台调试
- 使用 `window.modelViewer` 访问主应用实例
- 各管理器实例可通过modelViewer实例访问
- 开启浏览器开发者工具查看Three.js性能面板
### 性能优化
- 大模型文件建议压缩优化
- 使用LOD (Level of Detail) 技术
- 合理使用材质和纹理
- 避免过度的实时计算
## 常见问题
### CORS错误
确保通过HTTP服务器访问而不是直接打开HTML文件
### 模型加载失败
检查模型文件路径和格式,确保.glb文件完整性
### Three.js版本兼容
项目基于Three.js r150+更新版本时注意API变更
### 内存泄漏
及时清理不需要的几何体、材质和纹理对象

View File

@ -17,6 +17,26 @@ console = Console()
logger = logging.getLogger(__name__)
def _display_chapters_recursive(chapters, indent_level=0):
"""递归显示章节结构"""
for chapter in chapters:
indent = " " * indent_level
# 根据层级设置不同的样式
if chapter.level == 1:
style = "bold blue"
elif chapter.level == 2:
style = "green"
else: # level 3
style = "yellow"
console.print(f"{indent}{chapter.title}", style=style)
# 递归显示子章节
if chapter.children:
_display_chapters_recursive(chapter.children, indent_level + 1)
@click.group()
def project():
"""项目管理命令"""
@ -90,9 +110,7 @@ def parse(scoring_file: str, deviation_file: str | None, template_file: str | No
# 显示模板章节(如果有)
if bid_structure.chapters:
console.print("\n📚 模板章节:")
for chapter in bid_structure.chapters:
indent = " " * chapter.level
console.print(f"{indent}{chapter.title}")
_display_chapters_recursive(bid_structure.chapters)
# 显示统计信息
stats_panel = Panel(
@ -193,8 +211,7 @@ def smart_parse(word_file: str):
# 显示生成的目录结构
console.print("\n📚 生成的目录结构:")
for chapter in bid_structure.chapters:
console.print(f" {chapter.title}")
_display_chapters_recursive(bid_structure.chapters)
# 显示统计信息
stats_panel = Panel(

View File

@ -56,6 +56,8 @@ class DocumentChapter(BaseModel):
id: str = Field(..., description="章节ID")
title: str = Field(..., description="章节标题")
level: int = Field(..., description="章节层级")
score: float | None = Field(default=None, description="评分值")
children: List['DocumentChapter'] = Field(default_factory=list, description="子章节")
template_placeholder: str | None = Field(default=None, description="模板占位符")
@ -297,11 +299,24 @@ class BidParser:
return criteria
def _extract_table_text(self, table) -> str:
"""提取表格内容为文本格式"""
"""提取表格内容为文本格式,处理合并单元格"""
lines = []
# 获取表格的基本信息
max_cols = max(len(row.cells) for row in table.rows) if table.rows else 0
for i, row in enumerate(table.rows):
cells = [cell.text.strip() for cell in row.cells]
cells = []
for j in range(max_cols):
if j < len(row.cells):
cell_text = row.cells[j].text.strip()
# 处理空单元格
if not cell_text:
cell_text = "[空]"
cells.append(cell_text)
else:
cells.append("[空]")
# 使用制表符分隔便于AI理解
line = "\t".join(cells)
lines.append(f"{i+1}: {line}")
@ -312,37 +327,41 @@ class BidParser:
"""使用AI解析评分表格"""
try:
prompt = f"""
提取表格中的评分项和分值并智能分类返回JSON
从复杂的评分表格中提取评分项和分值并智能分类返回JSON
表格内容
{table_text}
要求
1. 提取评分项名称和分值
2. 描述字段用简短概括不超过30字
3. 根据评分项内容智能分类重点区分商务和技术
1. 仔细分析表格结构即使有合并单元格也要正确提取
2. "评审内容""评分因素""评分标准"等列中提取评分项名称
3. "分值"列或评分标准描述中提取具体分值如3分540
4. 忽略总分构成等汇总信息只提取具体评分项
5. 智能分类各评分项
**技术类别**
- technical_solution: 技术方案技术完整性技术先进性技术路线
- technical_solution: 技术方案技术条款技术完整性技术先进性
- equipment_spec: 设备规格产品参数设备可靠性技术指标
- implementation: 项目实施施工方案进度计划实施能力
- quality_safety: 质量管理安全管理环境管理质量体系
- after_sales: 售后服务维保服务培训服务技术支持
- compliance: 技术资质认证证书技术合规性
- after_sales: 售后服务维保服务培训服务技术支持服务部分
- compliance: 技术资质认证证书技术合规性技术条款应答
**商务类别**
- commercial: 价格评分报价商务条件企业资质财务状况业绩投标保证金商务合规性
- commercial: 价格评分报价商务条件企业资质财务状况业绩商务条款应答响应文件制作质量同类项目业绩商务部分
**其他**
- other: 无法明确分类的项目
示例输入分析
- "响应文件制作质量 3分" 商务类别
- "同类项目业绩 5分" 商务类别
- "技术条款应答 2分" 合规类别
- "商务条款应答 2分" 商务类别
格式
{{
"scoring_criteria": [
{{"item_name": "报价", "max_score": 30, "description": "价格评分标准", "category": "commercial"}},
{{"item_name": "技术方案", "max_score": 40, "description": "技术方案评分", "category": "technical_solution"}},
{{"item_name": "企业资质", "max_score": 10, "description": "企业资质证明", "category": "commercial"}},
{{"item_name": "设备参数", "max_score": 20, "description": "设备技术指标", "category": "equipment_spec"}}
{{"item_name": "响应文件制作质量", "max_score": 3, "description": "文件格式内容要求", "category": "commercial"}},
{{"item_name": "同类项目业绩", "max_score": 5, "description": "项目经验证明", "category": "commercial"}},
{{"item_name": "技术条款应答", "max_score": 2, "description": "技术要求符合性", "category": "compliance"}}
]
}}
@ -356,8 +375,21 @@ class BidParser:
# 解析AI响应
try:
if not response or response.strip() == "":
logger.error("AI返回空响应")
return []
# 尝试清理响应内容
clean_response = response.strip()
if clean_response.startswith("```json"):
clean_response = clean_response[7:]
if clean_response.endswith("```"):
clean_response = clean_response[:-3]
clean_response = clean_response.strip()
# 直接解析JSON失败就抛出异常
result_data = json.loads(response)
result_data = json.loads(clean_response)
scoring_data = result_data.get("scoring_criteria", [])
@ -426,10 +458,17 @@ class BidParser:
{table_text}
请判断这个表格属于以下哪种类型
1. scoring - 评分表包含评分项分值评分标准等
1. scoring - 评分表包含评分项分值评分标准等内容例如
- "分值""评分标准""得分"等列
- 有具体的分值数字如3分540分等
- "商务部分""技术部分""服务部分"等分类
- 有评审内容和评分因素
2. deviation - 偏离表包含技术要求响应类型偏离说明等
3. other - 其他表格不是评分表也不是偏离表
注意即使表格结构复杂有合并单元格只要包含评分标准和分值信息就是评分表
只返回一个单词scoring deviation other"""
response = self._call_llm_api(prompt)
@ -684,40 +723,133 @@ class BidParser:
return chapters
def _generate_professional_chapters(self, scoring_criteria: List[ScoringCriteria]) -> List[DocumentChapter]:
"""基于评分标准生成专业目录结构"""
chapters = []
def _group_scoring_items(self, scoring_criteria: List[ScoringCriteria], category: TechnicalCategory) -> dict[str, List[ScoringCriteria]]:
"""对同一类别下的评分项进行智能分组"""
# 过滤出指定类别的评分项
category_items = [item for item in scoring_criteria if item.category == category]
# 获取涉及的技术类别
categories_used = set()
for criteria in scoring_criteria:
categories_used.add(criteria.category.value)
if not category_items:
return {}
groups = {}
for item in category_items:
item_name = item.item_name
group_key = None
# 规则1识别前缀模式如"平台要求-xxx"
if "-" in item_name:
prefix = item_name.split("-")[0].strip()
if len(prefix) <= 10: # 前缀不能太长
group_key = f"{prefix}要求"
# 规则2识别关键词分组
if not group_key:
keywords_mapping = {
"原型": "系统原型设计",
"展示": "系统原型设计",
"方案": "方案设计",
"投标": "方案设计",
"人员": "人员配置方案",
"配置": "人员配置方案",
"测试": "测试质量保障",
"工具": "测试质量保障",
"质保": "质保服务方案",
"售后": "售后服务方案",
"服务": "售后服务方案",
"企业": "企业资质证明",
"实力": "企业资质证明",
"认证": "技术认证证书",
"证书": "技术认证证书",
"适配": "技术认证证书"
}
for keyword, group_name in keywords_mapping.items():
if keyword in item_name:
group_key = group_name
break
# 规则3默认分组
if not group_key:
group_key = "其他要求"
if group_key not in groups:
groups[group_key] = []
groups[group_key].append(item)
return groups
def _add_sub_chapters(self, parent_chapter: DocumentChapter, groups: dict[str, List[ScoringCriteria]], chapter_num: str) -> None:
"""为父章节添加二三级子章节"""
if not groups:
return
sub_chapter_index = 1
for group_name, scoring_items in groups.items():
# 创建二级标题
sub_chapter_id = f"{parent_chapter.id}_{sub_chapter_index:02d}"
sub_chapter_title = f"{chapter_num}.{sub_chapter_index} {group_name}"
sub_chapter = DocumentChapter(
id=sub_chapter_id,
title=sub_chapter_title,
level=2,
template_placeholder=f"{{{{{sub_chapter_id}_content}}}}"
)
# 为二级标题添加三级标题(具体评分项)
item_index = 1
for scoring_item in scoring_items:
item_chapter_id = f"{sub_chapter_id}_{item_index:02d}"
item_title = f"{chapter_num}.{sub_chapter_index}.{item_index} {scoring_item.item_name}"
if scoring_item.max_score > 0:
item_title += f" ({scoring_item.max_score}分)"
item_chapter = DocumentChapter(
id=item_chapter_id,
title=item_title,
level=3,
score=scoring_item.max_score,
template_placeholder=f"{{{{{item_chapter_id}_content}}}}"
)
sub_chapter.children.append(item_chapter)
item_index += 1
parent_chapter.children.append(sub_chapter)
sub_chapter_index += 1
def _generate_professional_chapters(self, scoring_criteria: List[ScoringCriteria]) -> List[DocumentChapter]:
"""基于评分标准生成专业三级目录结构"""
chapters = []
# 1. 评标索引表(始终包含)
chapters.append(self._create_standard_chapter("evaluation_index"))
# 2. 合规响应表(如果有偏离项或合规类评分项)
if any(c.category == TechnicalCategory.COMPLIANCE for c in scoring_criteria):
chapters.append(self._create_standard_chapter("compliance_response"))
else:
# 即使没有合规类评分项,也添加偏离表章节(招投标标准要求)
chapters.append(self._create_standard_chapter("compliance_response"))
# 2. 合规响应表(始终包含
compliance_chapter = self._create_standard_chapter("compliance_response")
# 为合规章节添加二三级标题
compliance_groups = self._group_scoring_items(scoring_criteria, TechnicalCategory.COMPLIANCE)
self._add_sub_chapters(compliance_chapter, compliance_groups, "2")
chapters.append(compliance_chapter)
# 3. 根据评分项类别添加相应章节
category_order = [
"technical_solution",
"equipment_spec",
"implementation",
"quality_system",
"after_sales"
# 3-7. 技术章节
technical_chapters = [
("technical_solution", TechnicalCategory.TECHNICAL_SOLUTION, "3"),
("equipment_spec", TechnicalCategory.EQUIPMENT_SPEC, "4"),
("implementation", TechnicalCategory.IMPLEMENTATION, "5"),
("quality_system", TechnicalCategory.QUALITY_SAFETY, "6"),
("after_sales", TechnicalCategory.AFTER_SALES, "7")
]
for category_key in category_order:
if category_key in categories_used or category_key == "technical_solution":
# 技术方案章节始终包含(作为兜底章节)
chapters.append(self._create_standard_chapter(category_key))
for chapter_key, category, chapter_num in technical_chapters:
chapter = self._create_standard_chapter(chapter_key)
# 为每个技术章节添加二三级标题
category_groups = self._group_scoring_items(scoring_criteria, category)
self._add_sub_chapters(chapter, category_groups, chapter_num)
chapters.append(chapter)
# 4. 验收与绩效考核对应表(标准履约要求,始终包含)
# 8. 验收与绩效考核对应表(始终包含)
chapters.append(self._create_standard_chapter("contract_delivery"))
return chapters