bid-doc/SKILL.md
投标服务方案文档生成器。根据采购技术规范和评分标准,自动生成完整的投标服务方案文档(Word + 信息图)。当用户说"生成投标方案"、"做标书"、"做服务方案"、"按技术规范出文档"时使用此skill。
npx skillsauth add atxinsky/skills bid-docInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
根据采购技术规范和评分标准,自动生成完整的投标服务方案文档(Word + 信息图)。适用于培训类项目投标。
用户需提供:
如果是 .doc 文件,先用 win32com 转换为 .docx:
import win32com.client, pythoncom
pythoncom.CoInitialize()
word = win32com.client.Dispatch("Word.Application")
word.Visible = False
doc = word.Documents.Open(r"原始文件路径.doc")
doc.SaveAs2(r"转换后路径.docx", 16)
doc.Close()
del doc, word
pythoncom.CoUninitialize()
然后用 python-docx 读取所有段落和表格,提取:
关键:项目概况中的"培训目标"和表格中的"培训内容覆盖"可能不完全一致,以表格中的"培训内容覆盖"为准设计课程。
数据一致性清单(生成后必须交叉验证):
如果提供了评分标准图片,用 Read 工具查看图片内容,提取:
评分标准 → 文档章节映射(必须一一对应):
| 评分项 | 分值 | 对应章节 | 得分策略 | |--------|------|----------|----------| | 文件总体评价 | 6-10 | 全文结构 | 规范性、完整性、逻辑性 | | 项目团队 | 12-20 | 2.5 人员配置 | 需公司提供真实资质 | | 业绩情况 | 12-20 | 商务标 | 方案中不写,商务标单独提供 | | 服务方案 | 18-30 | 二、服务方案 | 核心得分项,必须深度 + 量化 | | 工作进度 | 8-13 | 三、工作进度 | 甘特图 + 四维保障 | | 专利数量 | 0-2 | 商务标 | 如有专利单独提供 | | 绩效评价 | 1-5 | — | 取决于历史供应商评价 |
使用 docx-js(Node.js)生成 .docx 文件。运行时需要 NODE_PATH="$(npm root -g)"。
文档结构(严格按评分标准覆盖):
封面(项目名称 + 应答人 + 日期)
目录
一、对项目的理解
1.1 对[甲方单位]的理解
1.2 对采购项目的理解
- 项目定位与目标
- 项目规模与实施要求
- 服务敏感点分析
1.3 项目重点与难点分析
二、服务方案(对应评分项"服务方案")
2.1 项目实施思路(五阶段闭环)
2.2 培训课程体系设计
- 课程模块总览(严格按技术规范"培训内容覆盖")
- N天课程安排表
- 课程设计亮点
2.3 培训方式与教学方法(6种教学法)
2.4 师资配备方案
2.5 实施组织形式与人员配置
- 项目组织机构
- 人员配置表(含人员清单和简介说明)
2.6 培训效果评估体系(用技术规范中的考核方式术语)
2.7 质量保障措施(三维品控)
2.8 设备设施配置方案
2.9 风险管理与应对(6类风险+应对表)
★ 项目管理措施(深化服务过程细节,见下方专项说明)
★ 质量控制节点(训前+训中+训后闭环)
三、工作进度及保证措施(对应评分项"工作进度及保证措施")
3.1 项目进度计划(8阶段进度表 + 每期日程)
3.2 进度保证措施(四维保障)
四、项目交付成果(技术规范要求的所有交付物)
五、售后服务承诺(含明确期限、范围、内容)
这是拉开"良"与"优"差距的核心章节。甲方要看到的是操作细节和量化指标,不是空话。
必须包含的维度(4-5个子节,每个都要有量化):
训前(6-7个节点):
需求确认 → 方案评审 → 师资试讲 → 课件终审 → 场地踏勘 → 物料清点 → (红色教学点踩点)
训中(日循环):
晨会布置 → 课堂督导 → 午间反馈 → 课后教研 → 日报汇总
训后(闭环):
满意度统计 → 效果评估报告 → 改进建议 → 资料归档 → 跟踪回访
编码要点:
创建一个包含所有信息图的 HTML 文件,风格要求:
需要的信息图(共14张):
每个信息图用唯一的 CSS class 命名,页面用 .page 容器包裹。
使用 Playwright 截图:
const { chromium } = require('playwright');
// 为每个信息图元素截取 PNG
// 选择器格式:'.page:nth-child(N) .class-name'
// 注意:需要 NODE_PATH="$(npm root -g)"
截图存放在 screenshots/ 目录。
使用 python-docx 将截图插入对应段落后面:
from docx import Document
from docx.shared import Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
doc = Document('方案.docx')
# 找到目标段落 -> doc.add_paragraph() 创建新段 -> 添加图片 -> 移动到目标位置
# 关键:按段落索引倒序插入,避免索引偏移
图片插入位置映射(根据段落内容关键词定位):
更新已有图片的技巧(不需要重新插入):
# 直接替换图片 blob,保持位置和尺寸不变
for rel_id, rel in doc.part.rels.items():
if "image" in rel.reltype:
image_part = rel.target_part
with open(new_image_path, 'rb') as f:
image_part._blob = f.read()
生成完成后,必须执行以下审查,这是从"良"冲"优"的关键。
以下表述禁止出现在最终文档中:
| 禁用表述 | 替换方案 | |---------|---------| | "我公司深刻理解" | 直接删除,陈述事实 | | "贡献力量" | "圆满完成" | | "以高度负责的态度和专业化的服务水准" | "以专业的服务水准" | | "量身定制" | "针对XX实际设计" | | "先进性、创新性和可操作性"三连 | "切实可行、有针对性" | | "一对一访谈"(对大规模培训不现实) | "代表性座谈"、"分组访谈" | | "确保...的XX性"万能句 | 具体说做什么 | | "N大核心模块"(数字可能与实际不符) | "核心培训模块" |
检测脚本:
ai_phrases = [
'我公司深刻理解', '贡献力量', '量身定制',
'高度负责的态度', '先进性、创新性和可操作性',
'一对一访谈',
]
text = '\n'.join([p.text for p in doc.paragraphs])
for phrase in ai_phrases:
if phrase in text:
print(f'⚠️ AI套话残留: {phrase}')
# 必须验证的项目:
checks = {
'人数×批次': '检查总人数 = 每批人数 × 批次数',
'天数口径': '正式天数 vs 含报到日,首次提到必须加括号说明',
'师资姓名': '课表中每位讲师必须在师资简介中有对应条目',
'师资头衔': '同一讲师在全文所有出处的单位名/职称必须一致',
'课程覆盖': '技术规范要求的每项培训内容都必须出现在课表或正文中',
'满意率数字': '全文中出现的满意率目标必须一致(如95%)',
'交付物': '技术规范列出的每项交付物都必须在第四章出现',
}
| 检查项 | 说明 | 典型错误 | |--------|------|----------| | 单位名称 | 必须精确到区/县级 | "成都市委党校" vs "成都市温江区委党校" | | 专家标签 | 必须与本项目课程匹配 | 讲党建课的讲师标签写成"宏观经济专家" | | 职称资质 | 必须满足技术规范要求 | 技术规范要求"中级及以上",讲师无明确职称 | | 简写一致 | 课表简写不能写错 | "高培中心" vs "高级培训中心" |
技术规范"项目概况"和"培训内容覆盖"中提到的每一项内容,都必须在方案中有对应安排:
# 提取技术规范中所有培训内容关键词,逐一在方案全文中搜索
for kw in spec_keywords:
if kw not in full_text:
print(f'❌ 技术规范要求但方案未覆盖: {kw}')
如果甲方/合作方后续提供了真实师资和课表,执行替换:
替换后必须重新执行 Step 7 全部检查。
当客户反馈"内容太少"或字数未达目标(如2万字),使用以下方法论进行迭代扩充。
import copy
from lxml import etree
from docx import Document
def expand_para(para, new_text):
"""替换段落文本,保留原有格式(字体、加粗等)"""
if not para.runs:
return
para.runs[0].text = new_text
for run in para.runs[1:]:
run.text = ''
def insert_para_after(ref_para, text):
"""在指定段落后插入新段落,继承格式"""
new_para = copy.deepcopy(ref_para._element)
ns = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
for r in new_para.findall(f'.//{ns}r'):
new_para.remove(r)
new_r = etree.SubElement(new_para, f'{ns}r')
if ref_para.runs:
rpr = ref_para.runs[0]._element.find(f'{ns}rPr')
if rpr is not None:
new_r.insert(0, copy.deepcopy(rpr))
new_t = etree.SubElement(new_r, f'{ns}t')
new_t.text = text
new_t.set('{http://www.w3.org/XML/1998/namespace}space', 'preserve')
ref_para._element.addnext(new_para)
| 优先级 | 章节 | 扩充方式 | 典型增量 | |--------|------|----------|----------| | 1 | 服务敏感点分析 | 每条加具体应对措施 | 每条+80-120字 | | 2 | 项目重点难点 | 每条加解决方案和量化指标 | 每条+60-100字 | | 3 | 实施思路/五阶段 | 每阶段加操作细节 | 每阶段+100-150字 | | 4 | 质量保障措施 | 每条从一句话展开为一段 | 每条+80-120字 | | 5 | 进度保证措施 | 加时间节点和责任人 | 每条+50-80字 | | 6 | 售后服务 | 加响应时间、服务期限等量化承诺 | 每条+60-100字 | | 7 | 风险管理 | 总述展开,每类风险加应急预案 | 总述+150字 | | 8 | 培训效果评估 | 加过程性评价、结果运用 | 每项+100-150字 | | 9 | 师资配备 | 总述加选拔标准和备选机制 | +100-150字 | | 10 | 项目交付成果 | 加资料规范和移交流程 | +80-120字 |
# 每轮修改后必须统计字数
doc2 = Document(doc_path)
total = sum(len(p.text) for p in doc2.paragraphs)
for t in doc2.tables:
for row in t.rows:
for cell in row.cells:
total += len(cell.text)
print(f'当前字数: {total},距目标还差: {20000 - total} 字')
p.text能搜到但run.text中搜不到len(p.text) < 200避免匹配已展开的段落insert_para_after会增加段落数量,后续段落索引全部后移,如需多处插入应从后往前或分轮处理| 禁用表述 | 替换方案 | 说明 | |---------|---------|------| | 深刻理解 | 充分了解 | 最典型AI套话 | | 贡献力量 | 圆满完成 | | | 量身定制 | 专门制定 / 针对XX实际设计 | | | 赋能 | 支撑 / 助推 | | | 助力 | 支持 / 帮助 | | | 打造 | 建设 / 建立 | | | 筑牢 | 夯实 | 党建文档高频 | | 构筑 | 构建 | | | 紧密结合 | 结合 | 出现频率最高,通常4+处 | | 深度融合 | 融合 | | | 有机融合 | 融合 / 统筹 | | | 全方位 | 全面 | | | 多维度 | 多角度 | | | 立体化 | 综合 | | | 系统化培训 | 系统培训 | | | 深入浅出 | 通俗易懂 | 讲师简介高频 | | 精心设计 | 合理设计 | | | 精心打造 | 合理建设 | | | 精心组织 | 周密组织 | | | 全面提升 | 提高 | | | 持续提升 | 逐步提高 | | | 不断提升 | 逐步提高 | | | 充分发挥 | 发挥 | | | 充分体现 | 体现 | | | 充分调动 | 调动 | | | 切实增强 | 增强 | | | 切实提高 | 提高 | | | 切实做到 | 做到 | | | 积极探索 | 探索 | | | 大胆创新 | 创新 | | | 勇于担当 | 担当 | | | 凝聚共识 | 统一认识 | | | 汇聚力量 | 集中力量 | | | 形成合力 | 协同配合 | | | 高质量发展 | 稳健发展 | | | 新质生产力 | 新型生产力 | | | 确保培训取得实效 | 确保培训达到预期效果 | | | 确保圆满完成 | 确保按期完成 | | | 先进性、创新性和可操作性 | 切实可行、有针对性 | 三连套话 | | 一对一访谈 | 代表性座谈 / 分组访谈 | 大规模培训不现实 |
"""AI去痕修复脚本模板"""
import sys
sys.stdout.reconfigure(encoding='utf-8')
from docx import Document
doc_path = r'文档路径.docx'
doc = Document(doc_path)
changes = []
# 替换映射表(根据实际文档调整)
replacements = {
'赋能': '支撑',
'紧密结合': '结合',
'全方位': '全面',
'多维度': '多角度',
'持续提升': '逐步提高',
'全面提升': '提高',
'量身定制': '专门制定',
'系统化培训': '系统培训',
'精心设计': '合理设计',
'深入浅出': '通俗易懂',
'深刻理解': '充分了解',
'充分调动': '调动',
'高质量发展': '稳健发展',
'筑牢': '夯实',
'深度融合': '融合',
'凝聚共识': '统一认识',
}
# 段落替换
for i, p in enumerate(doc.paragraphs):
for old, new in replacements.items():
if old in p.text:
for run in p.runs:
if old in run.text:
run.text = run.text.replace(old, new)
changes.append(f'[段落{i}] {old} → {new}')
# 表格替换
for ti, t in enumerate(doc.tables):
for ri, row in enumerate(t.rows):
for ci, cell in enumerate(row.cells):
for old, new in replacements.items():
if old in cell.text:
for p in cell.paragraphs:
for run in p.runs:
if old in run.text:
run.text = run.text.replace(old, new)
changes.append(f'[表{ti}-行{ri}-列{ci}] {old} → {new}')
doc.save(doc_path)
# 残留检查
doc2 = Document(doc_path)
ai_phrases = list(replacements.keys())
残留 = []
for i, p in enumerate(doc2.paragraphs):
for phrase in ai_phrases:
if phrase in p.text:
残留.append(f'[段落{i}] {phrase}')
print(f'AI去痕完成,共 {len(changes)} 处修改')
if 残留:
print(f'⚠️ 残留: {残留}')
else:
print('✅ 无残留')
AI词汇可能被 python-docx 拆分到多个 run 中(如"紧密"在一个run、"结合"在另一个run),这时 run.text.replace() 无法匹配。解决方案:
# 如果 p.text 中有但所有 run.text 中都没有,说明跨run了
if old in p.text and not any(old in run.text for run in p.runs):
# 合并所有run文本后替换,再写回第一个run
combined = ''.join(run.text for run in p.runs)
combined = combined.replace(old, new)
p.runs[0].text = combined
for run in p.runs[1:]:
run.text = ''
{项目名}_服务方案.docx — 纯文字版infographics_{项目名}.html — 信息图网页版{项目名}_服务方案_final.docx — 带信息图的最终版NODE_PATH="$(npm root -g)"reconfigure(encoding='utf-8')image_part._blob = new_data,不需要重新插入Document(path) 重新读取再保存,避免状态污染development
Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like "the xlsx in my downloads") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved.
testing
Use when creating new skills, editing existing skills, or verifying skills work before deployment
development
Use when you have a spec or requirements for a multi-step task, before touching code
documentation
Create detailed implementation plan with bite-sized tasks