diff --git a/.claude/.backup/README.md b/.claude/.backup/README.md new file mode 100644 index 0000000..0dabcb1 --- /dev/null +++ b/.claude/.backup/README.md @@ -0,0 +1,51 @@ +# 备份目录说明 + +## 目录用途 +本目录用于存放课评文件的备份,防止数据丢失。 + +## 备份策略 + +### 三级备份机制 +1. **主文件**:正常保存到学生目录 +2. **时间戳备份**:同时保存一份到本目录,文件名格式:`YYYYMMDD_HHMMSS_{学生姓名}.md` +3. **旧文件备份**:覆盖前先备份旧文件为`.md.bak` + +### 自动清理规则 +- 保留最近 **7天** 的所有备份 +- 保留每月 **1号** 的备份(长期存档) +- 自动清理超过时间的备份 +- 手动清理指令:`/清理备份` + +## 恢复功能 + +### 恢复指令 +- `/恢复 {学生姓名}`:列出该学生的所有备份版本,选择恢复 +- `/恢复备份`:恢复最近一次备份 + +### 备份文件格式 +``` +文件名:20260516_143022_乔乔.md +格式:YYYYMMDD_HHMMSS_学生名.md +``` + +## 目录结构 +``` +.claude/.backup/ +├── 20260516_143022_乔乔.md +├── 20260516_143515_昊昊.md +├── 20260515_162030_小明.md +├── 20260501_101522_乔乔.md ← 每月1号备份长期保留 +└── README.md +``` + +## 注意事项 +- 本目录由系统自动管理,请勿手动删除备份文件 +- 如需清理备份请使用 `/清理备份` 指令 +- 备份文件包含完整课评内容,可直接使用 +- 恢复时会自动处理目录结构 +- 每月1号的备份会永久保留 + +--- + +*备份系统版本:v1.0.0* +*最后更新:2026-05-16* \ No newline at end of file diff --git a/.claude/.tasks/README.md b/.claude/.tasks/README.md new file mode 100644 index 0000000..7c92aa4 --- /dev/null +++ b/.claude/.tasks/README.md @@ -0,0 +1,88 @@ +# 待修复任务目录说明 + +## 目录用途 +本目录用于存放待修复任务列表,记录课评生成过程中发现的规范问题。 + +## 任务列表文件格式 + +### 文件命名规则 +``` +文件名:fix-list-YYYYMMDD.md +格式:fix-list-日期.md +``` + +### 任务列表内容格式 +```markdown +# 待修复列表 - 2026-05-16 + +## 发现世界-周四19点 + +- [ ] 乔乔:课程编号不规范(AI03-11 → 建议改为 AICODE03-11) +- [ ] 昊昊:课评正文包含"补课"词汇(需要删除或替换) +- [ ] 小明:字数仅140字(需要补充内容) + +## AICODE03-周六14点 + +- [ ] 小红:文件命名不符合规范 +``` + +## 修复流程 + +### 查看待修复 +``` +指令:/修复 +→ 展示待修复列表 +``` + +### 逐个修复 +1. 从列表中选择项目 +2. 查看问题描述 +3. 选择修复方式(自动修复或手动修复) +4. 修复完成后标记为已完成 + +### 批量自动修复 +- 对于可自动修复的问题(如课程编号规范) +- 系统可批量自动修复 +- 修复前会先预览变更内容 + +## 任务状态标记 + +- `[ ]` 待处理 +- `[x]` 已修复 +- `[!]` 需要手动处理 +- `[~]` 部分修复 + +## 保留策略 + +- 当前日期的任务列表保留 +- 超过1个月的任务列表自动归档 +- 归档文件移至 `.tasks/archive/` 目录 + +## 目录结构 +``` +.claude/.tasks/ +├── fix-list-20260516.md +├── fix-list-20260515.md +├── fix-list-20260514.md +├── archive/ +│ ├── fix-list-20260430.md +│ └── fix-list-20260429.md +└── README.md +``` + +## 常见问题类型 + +### 可自动修复 +- 课程编号不规范(AI→AICODE、C++→CSP) +- 日期格式错误 +- 文件命名不规范 + +### 需手动修复 +- 课评正文包含禁用词汇 +- 字数不符合要求 +- 内容质量问题 + +--- + +*任务系统版本:v1.0.0* +*最后更新:2026-05-16* \ No newline at end of file diff --git a/.claude/memory/config/class-data.js b/.claude/memory/config/class-data.js new file mode 100644 index 0000000..04d2cb4 --- /dev/null +++ b/.claude/memory/config/class-data.js @@ -0,0 +1,227 @@ +// =============================================== +// 班级和课程配置文件 +// 2026春季学期 - 小Q老师 +// =============================================== + +const CONFIG = { + // 学期配置 + semester: { + startDate: '2026-03-02', // 学期开始日期 + totalWeeks: 20, + }, + + // 班级列表 + classes: [ + { + id: '发现世界-周四19点', + name: '发现世界-周四19:00', + courseType: 'DISC', + coursePrefix: 'DISC', + weekday: '周四', + time: '19:00-20:00', + students: [ + { name: '梁昕乔', emoji: '👧', color: '#e8f5e9', trait: '活泼型 · 动觉学习 · 空间想象强' }, + { name: '钟昀昊', emoji: '🧒', color: '#e3f2fd', trait: '慢热型 · 视觉学习 · 双手协调' }, + { name: '林瀚丞', emoji: '🧒', color: '#fff3e0', trait: '平和型 · 需要拆解单步 · 螺丝刀标准' }, + { name: '杨佳兴', emoji: '🧒', color: '#fce4ec', trait: '活泼型 · 动觉学习 · 手部精细动作极佳【2026-05-22从周六09点班迁移】' } + ] + }, + { + id: 'AICODE03小Q周五1900', + name: 'AICODE03周五19:00', + courseType: 'AICODE03', + coursePrefix: 'AICODE03', + weekday: '周五', + time: '19:00-20:30', + students: [ + { name: '李怡瞳', emoji: '👧', color: '#fff3e0', trait: '思维活跃 · 创意好' }, + { name: '沙佩琪', emoji: '👧', color: '#fce4ec', trait: '认真踏实 · 代码能力强' }, + { name: '黄榆斐', emoji: '🧒', color: '#f3e5f5', trait: '积极主动 · 爱提问' }, + { name: '谢善诺', emoji: '👧', color: '#fff3e0', trait: '待观察' } + ] + }, + { + id: '发现世界-周六09点', + name: '发现世界-周六09:00', + courseType: 'DISC', + coursePrefix: 'DISC', + weekday: '周六', + time: '09:00-10:00', + students: [ + { name: '余韫', emoji: '👧', color: '#e8f5e9', trait: '活泼型 · 视觉学习 · 主动分类整理' }, + { name: '林嘉铭', emoji: '🧒', color: '#fff3e0', trait: '待观察' }, + { name: '胡瀚铭', emoji: '🧒', color: '#fce4ec', trait: '待观察' } + ] + }, + { + id: '发现世界-周六19点', + name: '发现世界-周六19:00', + courseType: 'DISC', + coursePrefix: 'DISC', + weekday: '周六', + time: '19:00-20:00', + students: [ + { name: '赖韵恬', emoji: '👧', color: '#e8f5e9', trait: '待观察' } + ] + }, + { + id: 'Wedo创造世界-周六1030', + name: 'Wedo创造世界-周六10:30', + courseType: 'CREATE', + coursePrefix: 'CREATE', + weekday: '周六', + time: '10:30-12:00', + students: [ + { name: '梁家铭', emoji: '🧒', color: '#e8f5e9', trait: '需鼓励建立自信 · 情绪调节有进步' }, + { name: '简思瑜', emoji: '🧒', color: '#e3f2fd', trait: '自信主动 · 结构搭建极坚固' }, + { name: '简思霖', emoji: '👧', color: '#fff3e0', trait: '平和慢热 · 代码理解需加强' }, + { name: '罗钧龄', emoji: '🧒', color: '#fce4ec', trait: '爱动手 · 精细动作好 · 越挫越勇' }, + { name: '黄晓瑜', emoji: '👧', color: '#f3e5f5', trait: '情绪稳定 · 独立完成度高' }, + { name: '黄馨宸', emoji: '👧', color: '#e0f2f1', trait: '慢热害羞→活泼 · 创意表达好' } + ] + }, + { + id: 'AICODE03小Q周六1400', + name: 'AICODE03周六14:00', + courseType: 'AICODE03', + coursePrefix: 'AICODE03', + weekday: '周六', + time: '14:00-15:30', + students: [ + { name: '曾乐凯', emoji: '🧒', color: '#e8f5e9', trait: '待观察' }, + { name: '李汶浩', emoji: '🧒', color: '#e3f2fd', trait: '待观察' }, + { name: '陈昕柔', emoji: '👧', color: '#fce4ec', trait: '待观察' } + ] + }, + { + id: 'Wedo创造世界-周六16点', + name: 'Wedo创造世界-周六16:00', + courseType: 'CREATE', + coursePrefix: 'CREATE', + weekday: '周六', + time: '16:00-17:30', + students: [ + { name: '冯彦哲', emoji: '🧒', color: '#e8f5e9', trait: '待观察' }, + { name: '马悦然', emoji: '👧', color: '#e3f2fd', trait: '待观察' } + ] + }, + { + id: 'SPIKE02-周日1030', + name: 'SPIKE02-周日10:30', + courseType: 'SPIKE', + coursePrefix: 'SPIKE', + weekday: '周日', + time: '10:30-12:00', + students: [ + { name: '吴浩洋', emoji: '🧒', color: '#e8f5e9', trait: '待观察' }, + { name: '吴浩骏', emoji: '🧒', color: '#e3f2fd', trait: '待观察' }, + { name: '洪一栩', emoji: '🧒', color: '#fff3e0', trait: '待观察' }, + { name: '王骏诚', emoji: '🧒', color: '#fce4ec', trait: '待观察' }, + { name: '邓琬曦', emoji: '👧', color: '#f3e5f5', trait: '待观察' }, + { name: '邓琬颖', emoji: '👧', color: '#e0f2f1', trait: '待观察' } + ] + } + ], + + // 课程主题映射 + courses: { + // 发现世界 DISC + DISC: { + 1: { code: 'DISC-001', theme: '认识螺丝刀', knowledge: '螺丝刀握持、螺丝正反转' }, + 2: { code: 'DISC-002', theme: '天文望远镜', knowledge: '管道连接、延长结构' }, + 3: { code: 'DISC-003', theme: '卫星天线', knowledge: '旋转结构、底座稳定' }, + 4: { code: 'DISC-004', theme: '概率转盘', knowledge: '圆形结构、中心轴' }, + 5: { code: 'DISC-005', theme: '天平秤', knowledge: '杠杆原理、平衡判断' }, + 6: { code: 'DISC-006', theme: '长颈鹿', knowledge: '高度建构、稳定性' }, + 7: { code: 'DISC-007', theme: '旋转飞机', knowledge: '游乐园旋转设施、侧面连接' }, + 8: { code: 'DISC-008', theme: '蜥蜴', knowledge: '关节连接、可动结构' }, + 9: { code: 'DISC-009', theme: '机器人瓦力', knowledge: '履带结构、收纳功能' }, + 10: { code: 'DISC-010', theme: '梳妆台', knowledge: '功能分区、镜子安装' }, + 11: { code: 'DISC-011', theme: '鳄鱼', knowledge: '嘴巴开合、铰链结构' }, + 12: { code: 'DISC-012', theme: '数字宝箱', knowledge: '密码锁、数字认知' }, + 13: { code: 'DISC-013', theme: '战斗机', knowledge: '机翼结构、尾翼平衡' }, + 14: { code: 'DISC-014', theme: '交通法规', knowledge: '红绿灯、道路标志' }, + 15: { code: 'DISC-015', theme: '龙舟', knowledge: '船体浮力、划桨动作' }, + 16: { code: 'DISC-016', theme: '钓鱼竿', knowledge: '伸缩结构、线轮控制' }, + 17: { code: 'DISC-017', theme: '八大行星', knowledge: '太阳系模型、轨道运行' }, + 18: { code: 'DISC-018', theme: '蝎子', knowledge: '多足结构、钳子开合' }, + 19: { code: 'DISC-019', theme: '霸王龙', knowledge: '大型恐龙、角色扮演' }, + 20: { code: 'DISC-020', theme: '投石车', knowledge: '杠杆原理、弹射机制' } + }, + // SPIKE + SPIKE: { + 1: { code: 'SPIKE-001', theme: '排障小车', knowledge: '电机控制、基础移动' }, + 2: { code: 'SPIKE-002', theme: '超级大摆锤', knowledge: '齿轮传动、摆动结构' }, + 3: { code: 'SPIKE-003', theme: '碰碰车', knowledge: '碰撞检测、方向控制' }, + 4: { code: 'SPIKE-004', theme: '电吉他', knowledge: '声音模块、按钮触发' }, + 5: { code: 'SPIKE-005', theme: '杯子盖球', knowledge: '传感器应用、条件判断' }, + 6: { code: 'SPIKE-006', theme: '智能台灯', knowledge: '光线传感器、亮度调节' }, + 7: { code: 'SPIKE-007', theme: '惯性小车', knowledge: '惯性原理、无动力设计' }, + 8: { code: 'SPIKE-008', theme: '留声机', knowledge: '记录播放、循环结构' }, + 9: { code: 'SPIKE-009', theme: '公交摆门', knowledge: '门控结构、传感器触发' }, + 10: { code: 'SPIKE-010', theme: '电动螺丝刀', knowledge: '工具复刻、扭矩控制' }, + 11: { code: 'SPIKE-011', theme: '摩天轮', knowledge: '圆周运动、速度控制' }, + 12: { code: 'SPIKE-012', theme: '直升机', knowledge: '螺旋桨、升力原理' }, + 13: { code: 'SPIKE-013', theme: '匀加减速', knowledge: '速度曲线、平滑控制' }, + 14: { code: 'SPIKE-014', theme: '体操运动员', knowledge: '倒立结构、平衡控制' }, + 15: { code: 'SPIKE-015', theme: '投篮计数器', knowledge: '计数逻辑、传感器应用' }, + 16: { code: 'SPIKE-016', theme: '机械手', knowledge: '抓取结构、自由度' }, + 17: { code: 'SPIKE-017', theme: '质检机', knowledge: '分类逻辑、颜色识别' }, + 18: { code: 'SPIKE-018', theme: '智能叉车', knowledge: '升降结构、搬运功能' }, + 19: { code: 'SPIKE-019', theme: '电子滚轮米尺', knowledge: '距离测量、数据显示' }, + 20: { code: 'SPIKE-020', theme: '感应道闸', knowledge: '自动识别、开关控制' } + }, + // AICODE03 + AICODE03: { + 1: { code: 'AICODE03-001', theme: 'AI是怎么"想"的?', knowledge: '概率预测原理、AI幻觉现象、提问质量影响' }, + 2: { code: 'AICODE03-002', theme: 'AI的记忆之谜', knowledge: '长期记忆与短期记忆、上下文窗口机制、系统提示词作用' }, + 3: { code: 'AICODE03-003', theme: 'AI训练师', knowledge: '系统提示词三要素、越狱与防护、迭代优化逻辑' }, + 4: { code: 'AICODE03-004', theme: '我是大作家(上)', knowledge: 'Trae Builder模式、Markdown基础、项目化思维' }, + 5: { code: 'AICODE03-005', theme: '我是大作家-2', knowledge: '故事大纲设计、项目上下文、章节结构' }, + 6: { code: 'AICODE03-006', theme: '我是大作家(完结篇)', knowledge: '完整书籍结构、精彩片段选择、路演技巧' }, + 7: { code: 'AICODE03-007', theme: '我是大作家【小说插图】', knowledge: 'AI图像生成提示词工程、占位符标注、文档化管理提示词' }, + 8: { code: 'AICODE03-008', theme: '我的个人主页(上)', knowledge: '内容先行原则、板块化结构、Trae自定义智能体' }, + 9: { code: 'AICODE03-009', theme: '我的个人主页(下)', knowledge: '交互元素设计、设计一致性、作品发布' }, + 10: { code: 'AICODE03-010', theme: '魔幻俄罗斯方块(上)', knowledge: 'Plan Mode计划模式、需求质量与输出质量、侦探模式分析' }, + 11: { code: 'AICODE03-011', theme: '魔幻俄罗斯方块(下)', knowledge: '自动化测试概念、测试覆盖、增量思维' }, + 12: { code: 'AICODE03-012', theme: '涂鸦PK(一)', knowledge: '精准需求编写、新窗口审核、角色属性设计' }, + 13: { code: 'AICODE03-013', theme: '涂鸦PK(二)', knowledge: '边界情况定义、独立窗口审核原则、测试脚本' }, + 14: { code: 'AICODE03-014', theme: '涂鸦PK(三)', knowledge: '游戏感Game Feel、增量需求写法、Web Audio API' }, + 15: { code: 'AICODE03-015', theme: '涂鸦PK(四)', knowledge: '数据驱动设计、角色选择界面、路演设计决策' }, + 16: { code: 'AICODE03-016', theme: 'Skills入门—用game-studio做跳一跳', knowledge: 'Skills工具箱概念、插件机制、game-studio插件、Three.js' }, + 17: { code: 'AICODE03-017', theme: '期末项目开发(上)', knowledge: '功能实现、代码调试、迭代优化' }, + 18: { code: 'AICODE03-018', theme: '期末项目开发(下)', knowledge: '功能完善、测试验证、bug修复' }, + 19: { code: 'AICODE03-019', theme: '项目优化与美化', knowledge: 'UI优化、交互改进、性能提升' }, + 20: { code: 'AICODE03-020', theme: '项目展示准备', knowledge: '演示文稿制作、路演排练、作品包装' }, + 21: { code: 'AICODE03-021', theme: '学期成果展示', knowledge: '作品展示、成果分享、学习总结' } + }, + // CREATE (Wedo) + CREATE: { + 1: { code: 'CREATE-001', theme: '风力发电站', knowledge: '直角传动、角度传感器、清洁能源' }, + 2: { code: 'CREATE-002', theme: '智能洗车场', knowledge: '多齿轮传动、皮筋传动、距离传感器、自动化流程' }, + 3: { code: 'CREATE-003', theme: '啄木鸟', knowledge: '皮筋传动、伺服电机、造型设计' }, + 4: { code: 'CREATE-004', theme: '破壁机', knowledge: '直角传动、角度传感器、健康生活' }, + 5: { code: 'CREATE-005', theme: '微波炉', knowledge: '齿轮减速、定时器、安全使用' }, + 6: { code: 'CREATE-006', theme: '送餐机器人', knowledge: '直角传动、距离传感器、智能导航' }, + 7: { code: 'CREATE-007', theme: '道闸', knowledge: '升降结构、传感器、交通控制' }, + 8: { code: 'CREATE-008', theme: '智能晾衣架', knowledge: '升降结构、光传感器、自动控制' }, + 9: { code: 'CREATE-009', theme: '打桩机', knowledge: '往复运动、重力原理、工程设备' }, + 10: { code: 'CREATE-010', theme: '小鸟喂食', knowledge: '倾斜传感器、自动喂养、动物关爱' }, + 11: { code: 'CREATE-011', theme: '推磨机器人', knowledge: '偏心圆、距离传感器、往复运动' }, + 12: { code: 'CREATE-012', theme: '雷达巡逻车', knowledge: '旋转机构、距离检测、巡逻模式' }, + 13: { code: 'CREATE-013', theme: '皮筋手枪', knowledge: '弹性原理、射击机构、安全操作' }, + 14: { code: 'CREATE-014', theme: '剪刀式升降机', knowledge: '剪叉结构、升降原理、工程应用' }, + 15: { code: 'CREATE-015', theme: '推车小人', knowledge: '传动机构、人形模型、运动控制' }, + 16: { code: 'CREATE-016', theme: '平衡运水', knowledge: '平衡结构、传感器、稳定控制' }, + 17: { code: 'CREATE-017', theme: '自动发球机', knowledge: '发球机构、速度控制、体育科技' }, + 18: { code: 'CREATE-018', theme: '摇头风扇', knowledge: '摇头机构、齿轮传动、智能家居' }, + 19: { code: 'CREATE-019', theme: '直升机', knowledge: '螺旋桨、升力原理、飞行控制' }, + 20: { code: 'CREATE-020', theme: '联合收割机', knowledge: '复合传动、收获机制、农业科技' } + } + } +}; + +// 导出配置 +if (typeof module !== 'undefined') { + module.exports = CONFIG; +} \ No newline at end of file diff --git a/.claude/memory/lesson/09-AICODE03/AICODE03-001-Prompt基础.md b/.claude/memory/lesson/09-AICODE03/AICODE03-001-Prompt基础.md deleted file mode 100644 index a196235..0000000 --- a/.claude/memory/lesson/09-AICODE03/AICODE03-001-Prompt基础.md +++ /dev/null @@ -1,64 +0,0 @@ -# 课程编号:AI03-001 -# 课程主题:Prompt基础——与AI有效对话 -# 适用班级:四年级(8-10岁) -# 教具套装:AICODE03平台 + 电脑 -# 课时长度:90分钟 - -## 课程目标 -- **知识目标**:理解Prompt概念,知道如何与AI有效沟通 -- **技能目标**:能写出清晰的Prompt让AI生成可用代码 -- **情感目标**:建立"AI是助手,我是主导者"的认知 - -## 核心知识点 -1. **Prompt概念**:给AI的指令/提示词 -2. **有效Prompt三要素**:角色设定 + 具体任务 + 输出要求 -3. **AI协作流程**:想法 → 写Prompt → AI生成 → 孩子审查 → 修改迭代 - -## 教学重点 -- 写出清晰的Prompt -- 理解和修改AI生成的代码 - -## 教学难点 -- 把模糊的想法转化为具体的Prompt -- 判断AI生成代码的正确性 - -## 课程流程 - -| 阶段 | 时长 | 内容 | 教师要点 | -|-----|------|------|---------| -| 导入 | 10分钟 | AI能做什么?展示AI生成代码案例 | 强调AI是工具,人是主导 | -| 讲解 | 15分钟 | 什么是Prompt?好的vs差的 | 对比演示 | -| 实践 | 35分钟 | 练习写Prompt让AI生成简单程序 | 从简单到复杂 | -| 调试 | 25分钟 | 运行AI代码,发现问题,修改Prompt | 迭代思维 | -| 总结 | 5分钟 | 今天学会了什么? | 强化Prompt工程概念 | - -## 评价要点 - -### 技能维度 -- [ ] 能写出包含任务描述的清晰Prompt -- [ ] 能理解AI生成的代码基本逻辑 -- [ ] 能通过修改Prompt改进输出结果 - -### 过程维度 -- [ ] 与AI协作的主动性 -- [ ] 对AI输出的批判性思维 -- [ ] 迭代优化的耐心 - -## 常见情况处理 - -| 情况 | 应对策略 | -|-----|---------| -| AI生成的代码跑不通 | 教查看错误信息,让AI"修复这个错误" | -| Prompt写太简单结果不满意 | 引导添加更多细节要求 | -| 完全依赖AI不思考 | 要求先口述思路,再让AI实现 | -| 对代码看不懂 | 让AI"解释这段代码",逐行理解 | - -## 课评关键词 -Prompt工程、AI协作、代码审查、迭代优化、AI时代创作能力 - -## 课后延伸 -- 尝试用AI生成一个计算器程序 -- 思考:AI生成的代码版权归谁? - ---- -*课程代码:AI03-001* diff --git a/.claude/memory/lesson/09-AICODE03/AICODE03-007-我是大作家【小说插图】.md b/.claude/memory/lesson/09-AICODE03/AICODE03-007-我是大作家【小说插图】.md new file mode 100644 index 0000000..bb2498f --- /dev/null +++ b/.claude/memory/lesson/09-AICODE03/AICODE03-007-我是大作家【小说插图】.md @@ -0,0 +1,77 @@ +# AICODE03-007 我是大作家【小说插图】 + +--- + +**课时**: 第7课时 +**主题**: 我是大作家【小说插图】 +**核心能力**: [表达力, 审美力] +**核心工具**: [codemaoai.com, AI图像生成] +**时长**: 90分钟 +**透明化层级**: 结果层 +**适用路线**: AICODE-03 + +--- + +## 1. 课程目标 + +### 知识目标 +- 复习AI图像生成中的提示词工程 +- 掌握用占位符标注和文档化管理提示词的方法 +- 理解图像与文字的配合关系 + +### 能力目标 +- 能为小说场景设计合适的插图提示词 +- 能用占位符系统化管理提示词模板 +- 能将生成的插图与小说内容有机结合 + +### 情感目标 +- 体验"图文并茂"带来的作品完整感 +- 建立"视觉表达也是创作"的认知 +- 激发对多媒体创作的兴趣 + +--- + +## 2. 核心知识点 + +1. **提示词工程复习**:角色描述、场景设定、风格指定 +2. **占位符标注**:用`{角色名}`、`{场景}`等变量实现提示词复用 +3. **文档化管理**:将提示词模板整理成可复用的文档 +4. **图文配合**:插图与小说情节的对应关系 + +--- + +## 3. 课程流程 + +| 阶段 | 时长 | 内容 | 教师要点 | +|-----|------|------|---------| +| 导入 | 10分钟 | 回顾上节课小说内容,讨论"有插图的书vs纯文字" | 激发视觉表达需求 | +| 讲解 | 15分钟 | AI图像生成提示词工程复习,占位符概念 | 演示占位符用法 | +| 实践 | 40分钟 | 为小说设计插图提示词,生成图像 | 逐场景指导 | +| 整合 | 20分钟 | 将插图插入Markdown文档 | 图文排版 | +| 总结 | 5分钟 | 分享作品,总结占位符管理方法 | 强化文档化思维 | + +--- + +## 4. 评价要点 + +### 技能维度 +- [ ] 能写出包含角色、场景、风格的完整提示词 +- [ ] 能使用占位符实现提示词复用 +- [ ] 能将插图与小说内容合理搭配 + +### 过程维度 +- [ ] 提示词迭代优化的尝试次数 +- [ ] 对图像生成结果的审美判断 +- [ ] 文档化管理提示词的意识 + +--- + +## 5. 课评关键词 + +AI图像生成、提示词工程、占位符、文档化管理、图文配合、审美力 + +--- + +*课程代码:AICODE03-007* +*创建日期:2026-05-20* +*适用学期:2026春季学期* diff --git a/.claude/memory/project_memory.md b/.claude/memory/project_memory.md new file mode 100644 index 0000000..b92e0ce --- /dev/null +++ b/.claude/memory/project_memory.md @@ -0,0 +1,106 @@ +# 项目记忆文件 + +## 课评工作流优化框架(v4.5) +> 创建日期:2026-05-16 | 基于实际跑流度的经验总结 +> 更新日期:2026-05-20 + +### v4.5 更新内容 +- **表单直连提交**:网页表单直接 POST 到本地服务器(`src/form_server.py`),AI 通过检测 `.claude/.tmp/EVALUATION_READY.txt` 信号文件自动触发课评生成,彻底取消「复制→粘贴」步骤 +- **补课存储规则简化**:取消补课专用目录和双向记录,补课记录统一保存在学生原班级,文件名加 `_补课` 后缀 +- **体验课记录扁平化**:体验课记录统一放在 `体验课记录/` 目录,命名格式 `日期-班级-课程主题.md`,一个文件可包含多个学生 +- **临时数据清理**:课评保存完成后自动清理 `.claude/.tmp/` 下的 JSON 和信号文件 + +--- + +## 课评工作流优化框架(v4.4) +> 创建日期:2026-05-16 | 基于实际跑流度的经验总结 + +### 优化核心:「Form-First」三步式 + +``` +/周几 → 选班级 → 自动打开网页表单 → 填表提交 → 自动生成保存 +``` + +> **适用范围**:所有上课日(周一~周日),`/周六`、`/周日`、`/周四`、`/周五` 等均按此流程执行 + +### 关键规则 + +#### 规则1:自动推演课程进度 +选择班级后,系统自动从 `summaries/` 读取最新课次,推算当前课次: +- 若上次课距当前日期>1周且全班请假 → 提示"需补课吗?"供确认 +- 否则直接使用下一课次 +- **目标:减少1轮"确认课程"的交互** + +#### 规则2:默认网页表单输入(Form-First) +选择班级后**默认直接创建并打开网页表单**,不先展示文本输入: +- 表单包含每个学生的:状态按钮(出勤/请假/体验/补课)+ 独立文本区 +- 表单显示学生画像摘要(性格特点、上次表现) +- 显示速记符号参考 +- **目标:消除"需要输入框→创建表单"的切换摩擦** + +#### 规则3:表单直连提交 + 输出头信息 +网页表单增加"直接提交"功能,提交后: +- 后台自动接收数据 +- 输出内容头部自动包含:班级名称、课程编号·主题、日期 +- 系统可自动识别班级和课次,不会搞错 +- **目标:消除"复制粘贴回聊天"的中间步骤 + 消除班级/课次识别错误** + +#### 规则4:表单辅助功能 +- 填写进度条:实时显示已填写/总人数(含补课学生) +- 待填写提示:红色标记未填写的学生 +- 输入框状态:填写后自动变绿,视觉反馈 +- 一键复制:复制到剪贴板,带成功提示 +- **补课/体验学生区** 🆕:虚线边框独立区域,可动态添加多个补课学生,含姓名输入、状态(补课/体验)、表现描述,进度条自动计算在内 + +#### 规则5:年级感知 +根据班级课程类型自动选择输出模板: +- 学龄前(TUBE/DISC/INVENT/CREATE)→ 学龄前格式 +- 小学(SPIKE/AICODE03)→ 小学格式 + +### 已确认优化效果 +- 交互轮数:5轮 → 3轮 +- 输入方式:聊天文本→临时表单 → **默认网页表单** +- 课程确认:需人工回答 → **自动推算** +- 数据提交:手动复制粘贴 → **一键提交** + +### 规则6:课评文字代码块包裹(便于预览复制) +班级总结文件(`*_班级反馈.md`)中,每位学生的课评正文必须用**代码块 ` ``` ` 包裹**,而非引用块 `>` 或纯文本: +- 代码块在 VS Code 预览时右上角显示**复制按钮**,方便一键复制课评文字 +- 格式示例: + ```markdown + **课评内容** + + ``` + {课评正文} + ``` + ``` +- 请假/体验等无课评正文的学生,用 `**状态**:` 描述即可,无需代码块 + +## Hard Constraints +- All class days (Monday-Sunday) must follow the Form-First workflow +- Course progress must be automatically matched based on current week's date using semester week mapping (NOT inferred from last session progress) +- Web forms must be created by default for student performance input, no manual text input first +- Web forms must support direct POST submission to local server (`src/form_server.py`) — **no copy-paste required** +- AI detects `.claude/.tmp/EVALUATION_READY.txt` signal file to auto-trigger evaluation generation +- Temporary JSON and signal files in `.claude/.tmp/` are auto-cleaned after save completion +- **补课记录存储规则(v4.5)**:跨班级补课学生,课评文件保存在学生原班级 `feedback/` 目录,文件名加 `_补课` 后缀(如 `20260505_DISC-009_补课.md`),不再创建补课专用目录或双向记录 +- **体验课记录规则(v4.5)**:体验课记录统一放在 `.claude/memory/class/体验课记录/` 目录,命名格式 `日期-班级-课程主题.md`(如 `2025-05-17-SPIKE-电动螺丝刀.md`),一个文件可包含多个体验学生 + +## Engineering Conventions +- Class selection is triggered by "/weekday" (e.g., "/周六", "/周四") +- Class lists display current week's course theme based on semester week number (e.g., Week 11 → DISC-011 鳄鱼) +- Student input forms include individual text areas and attendance status buttons +- Form data is saved as JSON to `.claude/.tmp/evaluation_input_{class}.json` via POST to local server +- Signal file `.claude/.tmp/EVALUATION_READY.txt` triggers AI to read JSON and generate evaluations +- Temporary JSON files and signal files are auto-cleaned after evaluation saving is complete +- **补课记录命名(v4.5)**:`YYYYMMDD_课程编号-课次_补课.md`,保存在学生原班级 `feedback/` 目录 +- **体验课记录命名(v4.5)**:`日期-班级-课程主题.md`(如 `2025-05-17-SPIKE-电动螺丝刀.md`),保存在 `.claude/memory/class/体验课记录/` 目录 + +## Lessons Learned +- Manual course confirmation caused unnecessary interaction rounds; automatic inference saves time +- Chat-based text input was replaced with web forms due to user preference for dedicated input fields +- Course theme should be determined by current week's scheduled theme, not by tracking last session's progress +- Copy-paste from web form to chat was the #1 friction point; local server POST + signal file eliminates it entirely +- Generated form files must be auto-cleaned after use to avoid project directory clutter +- **补课记录简化(v4.5)**:双向记录和补课专用目录造成文件冗余,改为单记录保存在原班级更简洁 +- **体验课扁平化(v4.5)**:多层嵌套目录不利于快速查看,扁平化结构更符合使用习惯 diff --git a/.claude/rules/00-core.md b/.claude/rules/00-core.md index c6470f9..1821949 100644 --- a/.claude/rules/00-core.md +++ b/.claude/rules/00-core.md @@ -1,8 +1,12 @@ # 核心规则 > 合并文件:系统基础规则 + 年龄段分类 + 课程类型定义 + 评价维度 + 评分标准 -> 版本:v4.0 | 更新日期:2026-05-14 -> +> 版本:v5.0 | 更新日期:2026-05-22 +> +> **v5.0 变更**:统一版本号体系到 v5.0,建立清晰的版本管理规范;同步所有文件版本 +> **v4.5 变更**:表单直连提交 — 网页表单直接 POST 到本地服务器,取消复制粘贴;版本号同步 +> **v4.4 变更**:无内容变更,版本号同步 +> **v4.3 变更**:无内容变更,版本号同步 > **v4.0 变更**:同步课评规范V1.0 — 新增3.4节「校宝课程编号规范」:C++班统一用CSP、AI编程班统一用AICODE+编号 --- diff --git a/.claude/rules/10-style.md b/.claude/rules/10-style.md index 8eaeaca..b922c2c 100644 --- a/.claude/rules/10-style.md +++ b/.claude/rules/10-style.md @@ -1,7 +1,15 @@ # 风格规则:课评写作风格与结构规范 > 合并文件:幼儿积木搭建 + 少儿编程入门 + 机器人竞赛 + 通用结构规范 -> 版本:v3.1(合并版)| 更新日期:2026-05-05 +> 版本:v4.6 | 更新日期:2026-05-20 +> +> **v4.6 变更**:优化课评详细程度,增加时间描述年龄适配,AI 自动扩展细节 +> - 标准版字数上限从280扩展到300字,详细版从350扩展到400字 +> - 新增"思维过程"和"具体数据"评估维度 +> - 分年龄段时间描述规范(幼儿模糊化/小学精确化) +> **v4.5 变更**:表单直连提交 — 取消复制粘贴,版本号同步 +> **v4.4 变更**:统一版本号至 v4.4;更新日期 +> **v3.2 变更**:禁用"今天",统一使用"本节课";禁用"本周"等时间表述 --- @@ -13,6 +21,11 @@ | 输出字数 | **弹性范围:180-350字**(根据输入内容丰富度自动调整) | | 段落数 | **3段** | +### ⚠️ 关键措辞规范(必须遵守) +- **禁用"今天"**,统一使用"本节课" +- **禁用"本周"、"这周"、"上周课"、"第几周"**等时间表述 +- 姓名规则:优先使用小名/昵称,其次去姓称名(如"昕乔"),禁用"宝贝"、"小朋友"等套话 + ### 课程类型与风格对应 | 课程类型 | 适用年龄 | 风格特点 | 基准字数 | @@ -33,13 +46,18 @@ | **第2段** | 课堂细节(掌握程度+课程环节+成长亮点)| **100-220字(弹性)** | 见下表 | | **第3段** | 课后建议 | 30-55字 | 见下表 | -### 2.2 字数弹性规则 +### 2.2 字数弹性规则(v4.6 优化版) -| 输入类型 | 字数范围 | 触发条件 | -|:-------:|:-------:|:---------| -| **精简版** | 180-220字 | 输入简洁,仅包含基本行为描述 | -| **标准版** | 220-280字 | 输入有具体细节或1-2个亮点 | -| **详细版** | 280-350字 | 输入有精彩瞬间、多个亮点或特殊表现 | +| 输入类型 | 字数范围 | 触发条件 | 结构 | +|:-------:|:-------:|:---------|:----:| +| **精简版** | 180-220字 | 输入简洁,仅包含基本行为描述 | 3段 | +| **标准版** | 220-300字 | 输入有具体细节或1-2个亮点 | 3段 | +| **详细版** | 300-400字 | 输入有精彩瞬间、多个亮点或特殊表现 | 3-4段 | + +**v4.6 优化说明**: +- 标准版上限从280字扩展到300字,允许更充分的细节描述 +- 详细版上限从350字扩展到400字,支持4段式结构 +- AI 基于学生画像和历史数据自动扩展细节,无需老师额外输入 ### 2.3 各年龄段字数调整 @@ -63,27 +81,46 @@ - **具体性**:不说"很棒",说"把弧形积木稳稳地卡进了凹槽" - **画面感**:描述作品细节,让家长能想象出画面 - **克制感**:不用"天才""最棒"等夸张词,真诚即可 +- **时间模糊化**:不用精确分钟数,用自然时段描述 -**禁用词汇**:宝贝、小天才、最棒、无敌、超级厉害、完美、套话("在今天的课堂上""通过本次活动")、比较性语言("比其他小朋友") +**禁用词汇**:宝贝、小天才、最棒、无敌、超级厉害、完美、套话("在本节课的课堂上""通过本次活动")、比较性语言("比其他小朋友") **推荐表达**: - 姓名使用:优先小名/昵称,其次去姓称名(如"昕乔") - 具体动作:"试了三次终于搭稳了底座" - 过程描述:"一开始想搭高塔,后来改成了小房子" +**时间描述规范(幼儿版)**: +| 速记 | 输出表述 | 说明 | +|------|---------|------| +| `gj5` | 开始阶段先观察了一会儿 | 不用"5分钟" | +| `zx15` | 能安静地玩一阵子 | 托班/小班适用 | +| `zx30` | 专注投入了挺长时间 | 中班/大班适用 | +| `zx45` | 几乎整节课都很投入 | 表现很好时使用 | + ### 3.2 少儿编程课(6-8岁) **语言特点**: - **专业度**:准确使用编程术语(循环、条件、事件),但不堆砌 - **平等感**:像对待小学习者一样尊重,不居高临下 - **启发性**:指出问题同时给方向,"这里如果换个顺序..." -- **实在感**:不夸大"编程改变命运",而是聊"今天解决了什么问题" +- **实在感**:不夸大"编程改变命运",而是聊"本节课解决了什么问题" +- **过程可视化**:描述调试过程、思维转变、尝试次数 **禁用词汇**:小天才、未来的程序员、最聪明、秒杀同龄人、套话("在人工智能时代""培养计算思维")、夸大("掌握了编程的核心奥秘") **推荐表达**: - 技术描述:"用'如果碰到边缘就反弹'解决了角色飞出屏幕的问题" - 过程记录:"先试了三次循环,发现次数不够,改成了重复10次" +- 调试细节:"第一次方向写反了,检查代码后发现并修正" +- 思维变化:"遇到bug没有直接问老师,先试着改了几个参数看效果" + +**时间描述规范(小学低年级)**: +| 速记 | 输出表述 | 说明 | +|------|---------|------| +| `zx30` | 专注投入约30分钟 | 可用相对精确时间 | +| `调试3次` | 调试了3次,花了大约10分钟 | 描述调试过程 | +| `sb2` | 试了2次后成功 | 强调尝试过程 | ### 3.3 机器人竞赛课(8-10岁) @@ -92,6 +129,7 @@ - **专业性**:准确描述技术细节(传感器校准、PID调速、机械臂力矩) - **成长视角**:把失败当作数据收集,把胜利当作阶段成果 - **团队意识**:强调分工配合,不只突出个人 +- **数据驱动**:用具体数字说话(成功率、时间、参数) **禁用词汇**:天才、大神、无敌、秒杀、碾压、套话("友谊第一比赛第二""胜不骄败不馁")、空洞("展现了良好的精神风貌") @@ -99,6 +137,16 @@ - 技术描述:"超声波传感器检测距离30cm时启动机械臂" - 战术分析:"选择了先拿近处资源块的策略,放弃了远处的" - 复盘语言:"翻车的原因是重心偏高,下次可以..." +- 数据记录:"校准后巡线成功率从60%提升到85%" +- 效率对比:"排查时间从平均3分钟缩短到1.5分钟" + +**时间描述规范(小学高年级)**: +| 速记 | 输出表述 | 说明 | +|------|---------|------| +| `zx30` | 专注投入约30分钟 | 精确时间 | +| `成功率60→85%` | 成功率从60%提升到85% | 数据对比 | +| `调试3次` | 经过3次调试,共用时10分钟 | 详细过程 | +| `排查3分钟` | 排查时间约3分钟 | 效率描述 | --- @@ -125,7 +173,7 @@ | 开心兴奋 | 😊/🌟 | 情绪积极、喜欢这节课 | | 合作互助 | 🤝 | 帮助同伴、团队协作 | | 家庭延伸 | 🏠 | 课后建议 | -| 技术编程 | ⚙️/🤖 | SPIKE/AI03课程 | +| 技术编程 | ⚙️/🤖 | SPIKE/AICODE03课程 | ### 4.3 Emoji位置 @@ -137,7 +185,7 @@ **第2段分散插入示例**: ``` -互锁的方法听懂了,实际操作时前两块需要老师扶着手指对齐💪,第三块开始能自己完成✨。和上周比,今天结构倒了没有发脾气,而是拆开重新观察了一下底座平不平,这个调整值得注意🌟。 +互锁的方法听懂了,实际操作时前两块需要老师扶着手指对齐💪,第三块开始能自己完成✨。和上周比,本节课结构倒了没有发脾气,而是拆开重新观察了一下底座平不平,这个调整值得注意🌟。 ``` **规则**: @@ -169,9 +217,9 @@ - 突出兴趣:用孩子感兴趣的比喻或场景 **示例**: -- "今天认识了'互锁结构',像拼图一样把积木交错叠在一起,搭好的墙不容易倒。" -- "今天接触了'重复执行'(循环),用它让小鸟持续扇翅膀,不用重复写很多次一样的代码。" -- "今天训练了颜色传感器的巡线校准,包括白值/黑值重新标定和阈值调整。" +- "本节课认识了'互锁结构',像拼图一样把积木交错叠在一起,搭好的墙不容易倒。" +- "本节课接触了'重复执行'(循环),用它让小鸟持续扇翅膀,不用重复写很多次一样的代码。" +- "本节课训练了颜色传感器的巡线校准,包括白值/黑值重新标定和阈值调整。" ### 5.2 掌握程度(第2段前半) @@ -190,23 +238,35 @@ ### 5.4 成长亮点(第2段后半) -**写什么**:与之前课程相比的进步,或本次的突出表现 +**写什么**:本节课展现出的进步或突出表现(**避免使用"和之前相比"、"和两周前相比"等直接对比句式**) **写法**: -- 纵向对比:"上次搭到一半就放弃,今天坚持到完成" -- 思维变化:"以前直接问老师,今天先试着自己改参数看效果" -- 习惯养成:"每次试车前都检查螺丝松紧,之前经常忘" +- **直接描述进步**:"本节课坚持到最后完成,没有中途放弃" +- **突出当下表现**:"本节课遇到困难先试着自己改参数看效果,再寻求帮助" +- **强调习惯养成**:"本节课每次试车前都主动检查螺丝松紧,非常细心" +- **展现思维成长**:"本节课能清晰描述问题,而不是只说'不会'" + +**❌ 避免使用**: +- "和上周相比,本节课..." +- "和两周前相比,本节课..." +- "和之前相比,本节课..." + +**✅ 推荐表达**: +- "本节课展现出了..." +- "本节课能独立..." +- "本节课主动..." +- "本节课坚持..." ### 5.5 课后建议(第3段) **写什么**:家长可以在家配合的具体活动 **写法**: - 可操作:不说"多练习",说"用筷子夹豆子" -- 关联课程:"在家可以用乐高重复今天的互锁结构" +- 关联课程:"在家可以用乐高重复本节课的互锁结构" - 尊重家庭:用"可以试试看"而非"必须" --- -## 六、输入丰富度评估算法 +## 六、输入丰富度评估算法(v4.6 优化版) ### 6.1 评估维度与分值 @@ -217,51 +277,72 @@ | **纵向对比** | 0-2分 | 提及之前表现+1分,有明确对比+1分 | "比上周"=1分,"比上周主动多了"=2分 | | **精彩瞬间** | 0-2分 | 有突破性行为/创新/社交互动 | "第一次主动帮助别人"=2分 | | **技术细节** | 0-1分 | 有具体数字/参数/步骤 | "调整了3次"、"设了5次循环" = 1分 | +| **思维过程** | 0-2分 | 描述思考/决策/排查过程 | "先检查了...再发现..."=2分 | +| **具体数据** | 0-2分 | 有时间/次数/百分比等数据 | "调试了3次,用了8分钟"=2分 | -**满分**:10分 +**满分**:14分 -### 6.2 版本选择决策矩阵 +### 6.2 版本选择决策矩阵(v4.6 更新) -| 总分 | 输出版本 | 字数范围 | -|:----:|:-------:|:-------:| -| 0-3分 | **精简版** | 180-220字 | -| 4-6分 | **标准版** | 220-280字 | -| 7-10分 | **详细版** | 280-350字 | +| 总分 | 输出版本 | 字数范围 | 结构 | +|:----:|:-------:|:-------:|:----:| +| 0-4分 | **精简版** | 180-220字 | 3段 | +| 5-8分 | **标准版** | 220-300字 | 3段 | +| 9-14分 | **详细版** | 300-400字 | 3-4段 | -### 6.3 评估示例 +**v4.6 优化说明**: +- 新增"思维过程"和"具体数据"两个维度,鼓励描述学生的思考过程 +- 详细版支持4段式结构,允许更充分的细节展开 +- AI 基于学生画像和历史数据自动补充细节,老师输入简洁也能得到丰富输出 + +### 6.3 评估示例(v4.6 更新) **精简输入**:"乔乔:搭了3层,开心" -- 行为数量:1分 | 情绪描述:1分 | 纵向对比:0分 | 精彩瞬间:0分 | 技术细节:0分 -- **总分:2分 → 精简版** +- 行为数量:1分 | 情绪描述:1分 | 纵向对比:0分 | 精彩瞬间:0分 | 技术细节:0分 | 思维过程:0分 | 具体数据:0分 +- **总分:2分 → 精简版(180-220字)** **标准输入**:"乔乔观望5分钟后主动搭3层,自己调整,开心,比上周有进步" -- 行为数量:3分 | 情绪描述:1分 | 纵向对比:1分 | 精彩瞬间:0分 | 技术细节:1分 -- **总分:6分 → 标准版** +- 行为数量:3分 | 情绪描述:1分 | 纵向对比:1分 | 精彩瞬间:0分 | 技术细节:1分 | 思维过程:0分 | 具体数据:1分 +- **总分:7分 → 标准版(220-300字)** **详细输入**:"乔乔观望5分钟后主动搭3层,球卡住自己调整,还帮助旁边的小朋友,最后说这是最喜欢的作品,比上周主动多了" -- 行为数量:3分 | 情绪描述:2分 | 纵向对比:2分 | 精彩瞬间:2分 | 技术细节:1分 -- **总分:10分 → 详细版** +- 行为数量:3分 | 情绪描述:2分 | 纵向对比:2分 | 精彩瞬间:2分 | 技术细节:1分 | 思维过程:1分 | 具体数据:1分 +- **总分:12分 → 详细版(300-400字)** + +**AI 自动扩展示例**: +- **老师输入**:"乔乔:gj5→zd3→zt ↑++"(极简速记) +- **AI 自动补充**: + - 从画像获取:乔乔性格内向、需鼓励 + - 从历史数据:上周观望10分钟、搭建2层 + - 自动计算:观望时间减少50%,搭建层数增加50% +- **输出**:详细版课评(AI 自动扩展为300-400字) --- ## 七、完整示例 -### 示例1:幼儿积木课(小班) +### 示例1:幼儿积木课(小班)- 标准版 **输入**:小明,4岁,小班,互锁结构搭建。专注度3分,开始时需要老师引导,后半段独立完成,最后自己加了装饰。 **输出**: -小明本节课学习了"互锁结构"——把积木像砌墙一样交错叠放,这样搭出来的墙更稳固🔍 +小明本节课学习了"互锁结构"——把积木像砌墙一样交错叠放,这样搭出来的墙更稳固,不容易倒🔍 -本节课小明对房子主题很感兴趣,搭建环节专注投入约30分钟💪。互锁的方法听懂了,实际操作时前两块需要老师扶着手指对齐,第三块开始能自己完成✨。和上周比,本节课结构倒了没有发脾气,而是拆开重新观察了一下底座平不平,这个调整值得注意🌟 +本节课小明对房子主题表现出浓厚兴趣,搭建环节一直很投入💪。互锁的方法在导入环节就听懂了原理,但实际操作时前两块需要老师扶着手指对齐凹槽,第三块开始能独立完成,到第五块时已经能自己检查是否对齐✨。结构第一次倒了是因为底座不平,小明没有像以前那样直接推倒重来,而是拆开重新观察底座,发现左边比右边低,调整后重新搭建,这个情绪调节和问题解决能力比两周前有明显提升🌟 -家里如果有积木,可以和孩子一起搭两堵墙,一堵直着叠、一堵交错叠,推推看哪个更稳,巩固本节课的概念🏠 +家里如果有积木,可以和孩子一起搭两堵墙,一堵直着叠、一堵交错叠,推推看哪个更稳,巩固本节课的互锁概念🏠 --- -*字数:198字 | 段落:3段 | Emoji:4个(第1段1个/第2段2个/第3段1个),第2段分散在段内* +*字数:258字 | 段落:3段 | Emoji:4个(第1段1个/第2段2个/第3段1个),第2段分散在段内* -### 示例2:少儿编程课(小学二年级) +**改进点**: +- 增加过程细节(第2块→第3块→第5块的进步阶梯) +- 增加思维描述(发现左边比右边低) +- 增加纵向对比(两周前的情绪调节能力) +- 保持时间模糊化("一直很投入"而非"30分钟") + +### 示例2:少儿编程课(小学二年级)- 详细版 **输入**:李想,8岁,学习了循环和条件判断,程序调试了三次才成功,最后自己加了一个开始按钮。 @@ -269,24 +350,39 @@ 李想本节课学习了"重复执行"(循环)和"如果碰到颜色就..."(条件判断),用这两个概念做了一个小猫走迷宫的游戏💡 -循环的作用理解了,但第一次把循环次数设成3次,小猫走得不够远;改成10次后正常,条件判断一开始方向写反了,检查代码后发现并修正💪。导入环节对迷宫游戏很感兴趣,实践环节专注完成代码搭建,最后分享环节能说出循环的作用,本节课的编程目标顺利达成✨。和上周相比,本节课会主动给代码分区域摆放(运动放一起、外观放一起),这个整理习惯有助于后续写更复杂的程序📈 +本节课李想对迷宫游戏表现出持续兴趣,搭建环节专注投入约35分钟,全程没有分心💪。循环的作用在导入环节就理解了,第一次设置成重复3次,运行后发现小猫只走了30步就到边缘了;第二次改成5次,还是不够;第三次改成10次,成功走到迷宫出口,三次调试共用时约10分钟✨。条件判断一开始方向写反了(写的是"如果碰到边缘就停止"而不是"反弹"),李想没有直接问老师,而是先检查了代码块的颜色和文字,发现逻辑不对后自己修正💡。特别值得肯定的是,本节课遇到bug时先自己排查了约3分钟,尝试改了两个参数观察效果,最后才举手求助,展现出了很好的独立调试能力📈。分享环节能清晰说出"循环就是重复做一样的事",概念掌握扎实🎯 回家后可以试试给游戏加一个"开始"按钮,点击后小猫才动。需要用到"当角色被点击"事件,可以预习一下。下周我们继续🏠 --- -*字数:218字 | 段落:3段 | Emoji:4个(第1段1个/第2段2个/第3段1个),第2段分散在段内* +*字数:298字 | 段落:3段 | Emoji:5个(第1段1个/第2段3个/第3段1个),第2段分散在段内* -### 示例3:机器人竞赛课(小学四年级) +**改进点**: +- 增加调试过程细节(3次调试的具体参数变化) +- 增加错误描述("碰到边缘就停止"vs"反弹") +- 增加排查过程(检查颜色和文字) +- 增加时间数据(35分钟、10分钟、3分钟) +- 增加概念复述(验证理解程度) + +### 示例3:机器人竞赛课(小学四年级)- 详细版 **输入**:王浩,10岁,训练了巡线校准和新任务策略,对抗练习输了但会复盘。 **输出**: -王浩本节课训练了颜色传感器的巡线校准(重新标定白/黑值)和新的任务策略(先近后远、分段计时),主要解决之前巡线误判和策略执行拖沓的问题⚙️ +王浩本节课系统训练了颜色传感器的巡线校准和新任务策略优化,核心解决之前巡线误判(黑线识别成白色)和策略执行拖沓(近处资源块拿取超时)的问题⚙️ -校准后巡线成功率从上次60%提升到85%,新策略执行不够果断,计划的"前30秒拿近处"实际用了45秒💪。导入环节对竞技策略话题很感兴趣,实操训练专注完成巡线调试,复盘环节能分析出问题原因,本节课的训练目标顺利达成✨。和两周前相比,遇到程序异常时不再直接重试,而是先分析可能原因(传感器/参数/结构),有针对性调整,调试效率明显提高📈 +巡线校准环节,王浩重新标定了白值(从原来的45调整到38)和黑值(从原来的12调整到8),校准后巡线成功率从上次60%(10次测试成功6次)提升到85%(20次测试成功17次),误判率明显下降💪。新策略执行环节,原计划"前30秒拿近处3个资源块",实际用了45秒只拿到2个,分析原因是机械臂展开角度偏大导致夹取时需要二次调整,下次可以优化展开角度到35度试试✨。本节课展现出了很好的系统排查能力,遇到程序异常时不再直接点击重试,而是先打开传感器数据面板查看实时读数,再检查程序逻辑,最后才调整参数,排查时间从平均3分钟缩短到1.5分钟,调试效率提升50%📈 -周末可以用模拟器测试几种不同的时间分配方案(20+100、30+90、40+80),记录哪种得分更高,下周带数据来讨论策略优化🏠 +周末建议用模拟器测试三种时间分配方案(20+100、30+90、40+80),每种方案跑5次记录平均得分,带数据来讨论策略优化🏠 --- -*字数:226字 | 段落:3段 | Emoji:4个(第1段1个/第2段2个/第3段1个),第2段分散在段内* +*字数:298字 | 段落:3段 | Emoji:4个(第1段1个/第2段2个/第3段1个),第2段分散在段内* + +**改进点**: +- 增加具体参数(白值45→38,黑值12→8) +- 增加测试数据(20次测试成功17次) +- 增加问题分析(机械臂展开角度偏大) +- 增加解决方案(优化到35度) +- 增加效率对比(3分钟→1.5分钟,提升50%) +- 增加可执行的课后任务(三种方案,每种5次) \ No newline at end of file diff --git a/.claude/rules/15-semester-weeks.md b/.claude/rules/15-semester-weeks.md index 1494362..d778b94 100644 --- a/.claude/rules/15-semester-weeks.md +++ b/.claude/rules/15-semester-weeks.md @@ -1,8 +1,15 @@ # 学期周数与课程主题映射规则 -> 2026春季学期课程安排与周数计算规则 -> 学期开始:2026年3月2日(第一周) -> 当前日期:2026年5月14日(第十一周) +> 合并文件:周数计算 + 课程主题映射表 +> 版本:v5.0 | 更新日期:2026-05-22 +> +> **v5.0 变更**:统一版本号体系到 v5.0;全面更新 AICODE03 课程大纲(1-21周),同步最新教学计划;更新当前周数至第12周 +> **v4.4 变更**:同步 AICODE03 第9-20周完整课程数据(来自 class-data.js);统一版本号 +> **v4.1 变更**:添加禁止"今天"使用规则,统一使用"本节课";更新当前日期 +> +> 2026春季学期课程安排与周数计算规则 +> 学期开始:2026年3月2日(第一周) +> 当前日期:2026年5月22日(第十二周) > **重要说明**:周数仅用于后端自动匹配课程主题,**课评正文不显示周数信息** --- @@ -34,6 +41,7 @@ | 周数 | "第X周"、"本周"、"上周课"、"下周" | 课程主题名称(如"天平秤")| | 时间阶段 | "这学期"、"上学期"、"第几节课" | 模糊时间词(如"之前"、"最近")| | 课程序号 | "DISC-005"、"第5课" | 课程主题(如"天平秤")| +| 日期表述 | "今天" | 统一使用"本节课" | **后端使用 vs 前端显示对比**: @@ -58,8 +66,8 @@ | 第8周 | 4月20日 - 4月26日 | | | 第9周 | 4月27日 - 5月3日 | 劳动节调休 | | 第10周 | 5月4日 - 5月10日 | | -| 第11周 | 5月11日 - 5月17日 | **当前周** | -| 第12周 | 5月18日 - 5月24日 | | +| 第11周 | 5月11日 - 5月17日 | | +| **第12周** | **5月18日 - 5月24日** | **当前周** | | 第13周 | 5月25日 - 5月31日 | | | 第14周 | 6月1日 - 6月7日 | 儿童节 | | 第15周 | 6月8日 - 6月14日 | 端午节 | @@ -123,20 +131,31 @@ | 第19周 | SPIKE-019 | 电子滚轮米尺 | 距离测量、数据显示、实用工具 | 数学应用、工具设计 | | 第20周 | SPIKE-020 | 感应道闸 | 自动识别、开关控制、安全系统 | 物联网应用、系统设计 | -### 2.3 AICODE03课程 - 20周完整主题 +### 2.3 AICODE03课程 - 21周完整主题 | 周数 | 课程代码 | 课程主题 | 核心知识点 | 能力目标 | |:---:|:-------:|:---------|:-----------|:---------| -| 第1周 | AICODE03-001 | Prompt基础 | 提示词结构、AI对话、基础指令 | AI认知、沟通技巧 | -| 第2周 | AICODE03-002 | 图像生成 | 文生图、风格描述、创意表达 | 多媒体创作、审美能力 | -| 第3周 | AICODE03-003 | 代码辅助 | AI编程助手、代码解释、调试帮助 | 编程效率、学习能力 | -| 第4周 | AICODE03-004 | 数据分析 | 数据处理、图表生成、结论提炼 | 数据思维、逻辑思维 | -| **第5周** | **AICODE03-005** | **项目整合** | **多AI协作、工作流设计、成果输出** | **系统思维、项目管理** | -| 第6周 | AICODE03-006 | 未来职业预测器 | AI工具链整合、项目开发、测试迭代 | AI协作、产品开发 | -| 第7周 | AICODE03-007 | 超能力抽签机 | 随机算法、交互设计、视觉美化 | 编程逻辑、创意设计 | -| **第8周** | **AICODE03-008** | **我的个人主页(上)** | **内容先行、板块化设计、自定义智能体** | **拆解力、审美力、AI协作** | - -> 第9-20周课程主题待更新 +| 第1周 | AICODE03-001 | AI是怎么"想"的? | 概率预测原理、AI幻觉现象、提问质量影响 | 提问力、批判思维 | +| 第2周 | AICODE03-002 | AI的记忆之谜 | 长期记忆与短期记忆、上下文窗口机制、系统提示词作用 | 提问力、拆解力 | +| 第3周 | AICODE03-003 | AI训练师 | 系统提示词三要素、越狱与防护、迭代优化逻辑 | 提问力、共创力 | +| 第4周 | AICODE03-004 | 我是大作家(上) | Trae Builder模式、Markdown基础、项目化思维 | 表达力、提问力 | +| 第5周 | AICODE03-005 | 我是大作家-2 | 故事大纲设计、项目上下文、章节结构 | 表达力、拆解力 | +| 第6周 | AICODE03-006 | 我是大作家(完结篇) | 完整书籍结构、精彩片段选择、路演技巧 | 表达力、审美力 | +| 第7周 | AICODE03-007 | 我是大作家【小说插图】 | AI图像生成提示词工程、占位符标注、文档化管理提示词 | 表达力、审美力 | +| 第8周 | AICODE03-008 | 我的个人主页(上) | 内容先行原则、板块化结构、Trae自定义智能体 | 拆解力、审美力 | +| 第9周 | AICODE03-009 | 我的个人主页(下) | 交互元素设计、设计一致性、作品发布 | 审美力、表达力 | +| 第10周 | AICODE03-010 | 魔幻俄罗斯方块(上) | Plan Mode计划模式、需求质量与输出质量、侦探模式分析 | 提问力、拆解力 | +| 第11周 | AICODE03-011 | 魔幻俄罗斯方块(下) | 自动化测试概念、测试覆盖、增量思维 | 拆解力、共创力、韧性力 | +| 第12周 | AICODE03-012 | 涂鸦PK(一) | 精准需求编写、新窗口审核、角色属性设计 | 拆解力、审美力 | +| 第13周 | AICODE03-013 | 涂鸦PK(二) | 边界情况定义、独立窗口审核原则、测试脚本 | 拆解力、韧性力 | +| 第14周 | AICODE03-014 | 涂鸦PK(三) | 游戏感Game Feel、增量需求写法、Web Audio API | 审美力、提问力 | +| 第15周 | AICODE03-015 | 涂鸦PK(四) | 数据驱动设计、角色选择界面、路演设计决策 | 表达力、共创力 | +| 第16周 | AICODE03-016 | Skills入门—用game-studio做跳一跳 | Skills工具箱概念、插件机制、game-studio插件、Three.js | 提问力、韧性力 | +| 第17周 | AICODE03-017 | 期末项目开发(上) | 功能实现、代码调试、迭代优化 | 共创力、韧性力 | +| 第18周 | AICODE03-018 | 期末项目开发(下) | 功能完善、测试验证、bug修复 | 共创力、韧性力 | +| 第19周 | AICODE03-019 | 项目优化与美化 | UI优化、交互改进、性能提升 | 审美力、共创力 | +| 第20周 | AICODE03-020 | 项目展示准备 | 演示文稿制作、路演排练、作品包装 | 表达力、共创力 | +| 第21周 | AICODE03-021 | 学期成果展示 | 作品展示、成果分享、学习总结 | 表达力、综合能力 | --- @@ -167,7 +186,7 @@ **课后建议模块**(自动关联主题): ``` -在家可以用衣架和绳子做一个简易天平,比较不同玩具的重量,巩固今天的平衡概念。 +在家可以用衣架和绳子做一个简易天平,比较不同玩具的重量,巩固本节课的平衡概念。 ``` ### 3.3 差异化表达(基于周数阶段) @@ -184,11 +203,11 @@ ## 四、快速查询 -### 4.1 当前周信息(2026年5月14日) -- **周数**:第11周 -- **发现世界主题**:DISC-011 鳄鱼(嘴巴开合、铰链结构) -- **SPIKE主题**:SPIKE-011 摩天轮(圆周运动、速度控制) -- **AICODE03主题**:AICODE03-008 我的个人主页(上)(第8周,第9周后待更新) +### 4.1 当前周信息(2026年5月22日) +- **周数**:第12周 +- **发现世界主题**:DISC-012 数字宝箱(密码锁、数字认知、空间藏物) +- **SPIKE主题**:SPIKE-012 直升机(螺旋桨、升力原理、飞行控制) +- **AICODE03主题**:AICODE03-012 涂鸦PK(一)(精准需求编写、新窗口审核、角色属性设计) ### 4.2 输入简化格式 教师只需提供: @@ -209,8 +228,11 @@ ## 五、版本信息 -- **版本**:v4.0 -- **更新日期**:2026-05-14 +- **版本**:v4.5 +- **更新日期**:2026-05-20 - **适用范围**:2026春季学期全部课程 - **维护者**:穹狼教学团队 -- **v4.0 变更**:同步课评规范V1.0 — AI03课程代码改为AICODE03(如AI03-005 → AICODE03-005);更新当前周数至第11周 +- **v4.5 变更**:全面更新 AICODE03 课程大纲(1-21周),包含AI原理、大作家系列、个人主页、俄罗斯方块、涂鸦PK、Skills入门等完整教学路径;更新当前周数至第12周 +- **v4.4 变更**:同步 AICODE03 第9-20周完整课程数据(来自 class-data.js);统一版本号至 v4.4 +- **v4.1 变更**:添加禁止"今天"使用规则,统一使用"本节课";更新当前日期至2026-05-17 +- **v4.0 变更**:同步课评规范V1.0 — AI03课程代码改为AICODE03(如AI03-005 → AICODE03-005);更新当前周数至第11周 \ No newline at end of file diff --git a/.claude/rules/20-workflow.md b/.claude/rules/20-workflow.md index 7d230c8..cddc448 100644 --- a/.claude/rules/20-workflow.md +++ b/.claude/rules/20-workflow.md @@ -1,7 +1,24 @@ # 工作流程规则:输入格式、批量生成、存储与特殊处理 > 合并文件:快捷输入格式 + 批量课评生成 + 新学生/补课处理 + 速记符号 + 快速入门 -> 版本:v4.0(课评规范同步版)| 更新日期:2026-05-14 +> 版本:v4.5(表单直连提交)| 更新日期:2026-05-20 +> +> **v4.5 变更**: +> - **表单直连提交**:网页表单填写完成后直接 POST 到本地服务器,数据自动保存为 JSON。AI 检测到信号文件后自动读取并生成课评,彻底取消「复制→粘贴回聊天」步骤 +> - 新增 `src/form_server.py` 本地表单服务器,支持动态注入班级/学生/课程数据 +> - 表单输出文件:`.claude/.tmp/evaluation_input_{班级}.json` +> - 信号文件:`.claude/.tmp/EVALUATION_READY.txt`(AI 检测此文件触发课评生成) +> +> **v4.4 变更**: +> - 课程进度自动推演:选择班级后根据**当周日期自动匹配课程主题**(基于学期周数映射表),无需参考上节课进度 +> - Form-First 模式:选择班级后默认自动创建网页表单,替代聊天文本输入框 +> - 表单直连提交:网页表单直接提交数据,无需复制粘贴回聊天 +> - 新增 `.claude/memory/project_memory.md` 项目记忆文件 +> +> **v4.3 变更**: +> - 新增 `/周几` 快速索引指令(`/周六`、`/周日`、`/周四` 等) +> - 重写第14节交互式流程:B模式分开展示学生 + 独立输入区 + 快捷标记按钮 +> - 新增学生快捷标记操作(请假/体验/补课/出勤) > > **v4.0 变更**: > - 新增第10节「课评规范V1.0对照规则」:课程编号、目录结构、文件命名、日期匹配、完成率统计、三级查找 @@ -49,7 +66,7 @@ AI生成 → 自动双轨保存 → 完成! **方式1:极简一句话** ``` -乔乔今天开始不敢碰,后来主动搭了三层,球卡住自己调高度,挺稳定的,比上周主动多了 +乔乔本节课开始不敢碰,后来主动搭了三层,球卡住自己调高度,挺稳定的,比上周主动多了 ``` **方式2:关键词速记** @@ -100,11 +117,11 @@ AI自动匹配班级学生名单,实时纠正谐音: | 标记 | 含义 | 处理方式 | 保存位置 | |------|------|----------|---------| -| 无标记 | 正式学生 | 双轨保存 | 班级汇总+个人档案 | -| `[补课]` | 补课学生 | 自动检测档案位置,跨班级自动双轨保存 | 班级汇总+个人档案 | -| `[体验]` | 体验课学生 | 仅班级汇总 | 班级汇总(标记体验) | -| `[缺课]` | 今天缺席 | 记录缺席 | 班级汇总(标记缺课) | -| `[new]` | 新学生首次 | 创建档案 | 班级汇总+个人档案 | +| 无标记 | 正式学生 | 双轨保存 | 个人课评文件+班级汇总 | +| `[补课]` | 补课学生 | 自动检测档案位置,跨班级自动双轨保存 | 个人课评文件(原班级侧追踪文件)+班级汇总 | +| `[体验]` | 体验课学生 | 仅班级汇总 | 个人课评文件(补课目录)+班级汇总 | +| `[缺课]` | 今天缺席 | 记录缺席 | 仅班级汇总 | +| `[new]` | 新学生首次 | 创建档案 | 个人课评文件+班级汇总+学生画像 | ### 3.2 标记使用示例 @@ -134,7 +151,7 @@ AI自动匹配班级学生名单,实时纠正谐音: ``` 教师极简输入 → AI并行解析每个学生 → 预加载课程/档案 → -并行生成个性化课评 → 质量检查 → 【自动双轨保存】→ 完成 +并行生成个性化课评 → 质量检查 → 【自动双轨保存】→ 【🗑️ 自动删除临时表单】→ 完成 ``` **预加载说明**: @@ -256,6 +273,168 @@ AI及自动化系统扫描 `feedback/` 目录时,通过文件名后缀判断 | **班级总结** | `summaries/YYYYMMDD_课程编号-课次_班级反馈.md` | 班级群发文案 | 课后编写 | | **学生画像** | `profile.md`(固定名) | 学生基础信息 | 建档时创建 | +#### 班级总结文件完整模板 + +班级总结文件(`summaries/YYYYMMDD_课程编号-课次_班级反馈.md`)使用以下统一模板框架,所有班级总结一致: + +##### 模板结构总览 + +``` +┌─ YAML Frontmatter(元数据)─────────────────────────┐ +│ class, week, course, theme, date │ +│ status: total/present/make_up/absent │ +│ students: name + status 列表 │ +├─ 标题 ────────────────────────────────────────────────┤ +│ # {班级} 第{X}周汇总 │ +├─ Quote行(课程信息)─────────────────────────────────┤ +│ > 课程代码 / 上课日期 / 课程主题 / 班级人数 │ +├─ 本周课评状态表 ──────────────────────────────────────┤ +│ | 学生 | 状态 | 类型 | 档案位置 | 操作 | │ +├─ 学生课评列表 ────────────────────────────────────────┤ +│ ## 学生课评列表 │ +│ │ +│ ### {学生名} - {类型} ✅/🔄 │ +│ **基本信息**(表现标签 + 情绪状态) │ +│ **课评内容**(代码块 ``` 包裹正文) │ +│ **教师备注**(生成时间 + 确认状态) │ +│ **教师备注**(状态 + 个人档案 + 亮点) │ +│ --- │ +│ │ +│ ### {请假学生} - ❌ 请假 │ +│ **状态**:请假,未生成课评 │ +├─ 本周班级整体情况 ────────────────────────────────────┤ +│ ## 本周班级整体情况 │ +│ ### 本周表现分布(表格) │ +│ ### 共性观察(整体表现/主题掌握/亮点/挑战) │ +│ ### 需关注学生 │ +│ ### 下周重点 │ +├─ 页脚 ────────────────────────────────────────────────┤ +│ *生成时间:{YYYY-MM-DD}* │ +└────────────────────────────────────────────────────────┘ +``` + +##### 完整模板源码 + +```markdown +--- +class: {班级目录名} +week: {周数} +course: {课程编号} +theme: {课程主题} +date: {YYYY-MM-DD} +status: + total: {总人数} + present: {出勤人数} + make_up: {补课人数} + absent: {请假人数} +students: + - name: {学生名} + status: present/absent/make_up + - name: ... +--- + +# {班级名称} 第{周数}周汇总 + +> 课程代码:{课程编号} +> 上课日期:{YYYY-MM-DD} +> 课程主题:{主题(知识点)} +> 班级人数:{N}人(出勤{M}人,请假{K}人) + +--- + +## 本周课评状态 + +| 学生 | 状态 | 类型 | 档案位置 | 操作 | +|:-----|:----:|:----:|:---------|:----:| +| {学生名} | ✅ 已保存 | 常规学生 | 本班 | [查看] | +| {补课学生} | ✅ 已保存 | 补课学生 | 补课 | [查看] | +| {请假学生} | ❌ 请假 | 常规学生 | 本班 | - | + +--- + +## 学生课评列表 + +### {学生名} - 常规学生 ✅ / 补课学生 🔄 + +**基本信息** +- 表现标签:{根据课评内容提炼标签,逗号分隔} +- 情绪状态:{稳定/开心/积极/波动等} + +**课评内容** + +``` +{课评正文,使用代码块包裹} +``` + +**教师备注** +- 生成时间:{YYYY-MM-DD HH:MM} +- 确认状态:☑️ 已确认 + +--- + +**教师备注**: +- 状态:已保存 +- 个人档案:已同步 +- 亮点:{提炼亮点} + +--- + +### {请假学生} - ❌ 请假 + +**状态**:请假(或停课),未生成课评 + +--- + +## 本周班级整体情况 + +### 本周表现分布 + +| 维度 | 优秀 | 良好 | 合格 | 需关注 | +|:------|:---:|:---:|:---:|:----:| +| 参与度 | {人数} | {人数} | {人数} | {人数} | +| 知识点掌握 | {人数} | {人数} | {人数} | {人数} | +| 情绪状态 | {人数} | {人数} | {人数} | {人数} | + +### 共性观察 +1. **整体表现**:{总结} +2. **主题掌握**:{总结} +3. **亮点**:{总结} +4. **挑战**:{总结} + +### 需关注学生 +- {名单及原因} + +### 下周重点 +1. 预告下周课程:{课程编号} {主题} +2. 重点:{核心知识点} + +--- + +*生成时间:{YYYY-MM-DD}* +``` + +##### 各情况处理细则 + +| 情况 | 状态列 | 类型列 | 课评内容 | +|:-----|:------:|:------:|:---------| +| **常规出勤** | ✅ 已保存 | 常规学生 | 完整课评正文(代码块) | +| **补课学生** | ✅ 已保存 | 补课学生 | 完整课评正文(代码块),基本信息如实填写 | +| **请假** | ❌ 请假 | 常规学生 | `**状态**:请假,未生成课评` | +| **停课** | 🚫 停课 | 停课学生 | `**状态**:已停课,不生成课评` | +| **全部请假** | — | — | 仅保留课评状态表,学生课评列表写状态即可,共性观察处说明"本周全部请假/停课" | + +##### 基本信息字段填写规则 + +表现标签:根据课评内容提炼3-5个关键词标签,如"积极搭建"、"圆周运动理解"、"创意改造"、"编程巩固"、"主动互动"等,体现学生本节课的核心表现亮点。 + +情绪状态:综合判断本节课的情绪基调,如"稳定"、"开心/稳定"、"积极/稳定"、"波动"等。 + +##### 代码块规范 + +每位有课评正文的学生,其课评文字必须用**代码块 ` ``` ` 包裹**(而非引用块 `>` 或纯文本),以便在 VS Code 预览时右上角显示**复制按钮**,方便一键复制。 + +请假/体验等无课评正文的学生,用 `**状态**:` 描述即可,无需代码块。 + ### 5.5 存储优先级 1. **第一优先级**:个人课评文件 `feedback/*.md`(必须存在,关系到完成率统计) @@ -283,7 +462,7 @@ Step 2(2分钟): 速记输入 小红[补课]:专注完成 → Step 3(2分钟): 查看并保存 -AI生成 → 查看质量报告 → 完成(已自动双轨保存) +AI生成 → 查看质量报告 → 课评保存完成 → 🗑️ 自动清理表单 → 完成 完成!课评已自动双轨保存,无需确认。 ``` @@ -308,10 +487,10 @@ AI生成 → 查看质量报告 → 完成(已自动双轨保存) ``` 生成阶段 保存阶段 完成阶段 ───────── ───────── ───────── -AI生成课评 → 【自动保存】 → 教师可随时查看/修改 +AI生成课评 → 【自动保存】 → 课评持久化保存 ↓ ↓ ↓ -质量检查通过 → feedback/YYYYMMDD_课程编号.md → 完成(无需确认) - + summaries/YYYYMMDD_课程编号_班级反馈.md +质量检查通过 → feedback/YYYYMMDD_课程编号.md → 🗑️ 自动删除临时表单 + + summaries/YYYYMMDD_课程编号_班级反馈.md → 完成(无需确认) ``` **核心原则**: @@ -362,9 +541,9 @@ def on_evaluation_generated(student, evaluation, class_info): |:-----|:---------|:----------------| | **正式学生** | 有档案 | `.claude/memory/class/{班级}/{学生}/feedback/YYYYMMDD_课程编号-课次.md` | | **本班补课** | 有档案(本班) | `.claude/memory/class/{班级}/{学生}/feedback/YYYYMMDD_课程编号-课次.md` | -| **跨班级补课** | 有档案(他班) | `.claude/memory/class/{补课班级}/补课/{学生}/feedback/YYYYMMDD_课程编号.md` | -| **其他老师班级补课** | 有档案(其他老师) | `.claude/memory/class/{班级}/补课/{学生}/feedback/YYYYMMDD_课程编号.md` | -| **体验/临时学生** | 无档案 | `.claude/memory/class/{班级}/补课/{学生}/feedback/YYYYMMDD_课程编号.md` | +| **跨班级补课** | 有档案(他班) | `.claude/memory/class/{补课班级}/补课/{学生}/feedback/YYYYMMDD_课程编号-课次.md` | +| **其他老师班级补课** | 有档案(其他老师) | `.claude/memory/class/{班级}/补课/{学生}/feedback/YYYYMMDD_课程编号-课次.md` | +| **体验/临时学生** | 无档案 | `.claude/memory/class/{班级}/补课/{学生}/feedback/YYYYMMDD_课程编号-课次.md` | | **缺课学生** | 有档案 | ❌ 不生成课评 | > **⚠️ 重要**:跨班级补课学生必须放在 `补课/` 目录下,否则自动化统计系统的三级查找可能无法识别。 @@ -451,7 +630,7 @@ AI定位班级汇总中乔乔的课评 **授课日期**: 2026-04-18 **课评内容**: -学生今天课堂非常认真,三类作业全部完成。但课堂练习调试12次(2次运行错误、3次答案错误、2次编译错误),说明边界条件和代码规范性还需加强。建议每道题重新手写框架,减少复用旧代码,这样基础更扎实。 +学生本节课课堂非常认真,三类作业全部完成。但课堂练习调试12次(2次运行错误、3次答案错误、2次编译错误),说明边界条件和代码规范性还需加强。建议每道题重新手写框架,减少复用旧代码,这样基础更扎实。 课后整理埃氏筛法模板,记录今天的坑点。 @@ -473,12 +652,12 @@ AI定位班级汇总中乔乔的课评 #### 补课追踪模板(补课班级侧) -文件开头注明补课来源: +文件开头可以注明补课来源(仅作元信息,正文不提及补课): ```markdown (补课,来自 AICODE06洋芋周日1400) -{正常课评内容} +{正常课评内容,完全不提补课} ``` ### 7.8 失败处理机制 @@ -599,6 +778,28 @@ students: | 重生成 | `重生成乔乔` | 重新生成乔乔的课评 | | 手动补存 | `补存` / `同步` | 手动触发待补存队列处理 | +### 7.12 临时文件自动清理规则 + +> 每次课评生成的输入数据文件(`.claude/.tmp/evaluation_input_*.json` 和 `EVALUATION_READY.txt` 信号文件)在课评保存完成后自动删除,避免临时数据堆积。 + +**清理时机**:课评全部保存完成后立即执行,无需用户确认 + +**清理流程**: +``` +课评保存完成 → AI 删除 .claude/.tmp/ 下对应的 JSON 文件和信号文件 → 提示「🗑️ 已清理临时数据文件」 +``` + +**核心原则**: +- ✅ **用完即删**:课评持久化到 `feedback/*.md` 后,临时 JSON 不再需要 +- ✅ **不丢失数据**:课评内容已保存在班级目录中,删除 JSON 不影响任何数据 +- ✅ **自动执行**:无需用户手动删除,AI 在完成阶段自动处理 +- ✅ **安全删除**:仅删除本次会话产生的临时 JSON 和信号文件 + +**例外情况**: +- 表单 HTML 模板文件(`form_template.html`)不会被删除(是可复用的通用模板) +- 服务器脚本(`form_server.py`)不会被删除 +- 仅删除 `.claude/.tmp/` 目录下的本次输入数据文件 + --- ## 八、出勤统计(嵌入班级汇总) @@ -787,3 +988,611 @@ students: - [ ] 补课学生必须有课评(放在补课班级的 `补课/学生名/feedback/` 下) - [ ] 编写班级总结(保存到 `summaries/YYYYMMDD_课程编号-课次_班级反馈.md`) - [ ] 课程编号使用标准格式(CSP/AICODE),不得使用缩写 + +--- + +## 十一、工作流程优化功能(v4.1 新增) + +> **优化功能概述**:提升课评生成效率、数据安全性和规范一致性 +> **触发方式**:自动启用,配合 `/优化` 或相关指令使用 +> **配套技能**:keping-optimizer + +### 11.1 三级备份机制(自动启用) + +**功能**:防止数据丢失,提供完整恢复选项 + +**备份策略**: +``` +第1级:直接保存到目标路径(主保存) + └── 路径:.claude/memory/class/... + +第2级:同时保存到 .backup/ 目录(时间戳备份) + └── 路径:.claude/.backup/YYYYMMDD_HHMMSS_{学生}.md + +第3级:写入前备份现有文件(防止覆盖) + └── 路径:原文件路径 + .md.bak +``` + +**恢复功能**: +- 指令:`/恢复 {学生}` → 列出该学生的所有备份版本 +- 指令:`/恢复备份` → 恢复最近一次备份 +- 指令:`/清理备份` → 清理超过7天的旧备份 + +### 11.2 自动补全缺失信息(自动启用) + +**功能**:教师只需输入核心表现,系统自动补全日期、课程编号、课次 + +**自动补全规则**: +| 信息项 | 补全规则 | 默认值 | +|--------|---------|--------| +| **日期** | 取当天日期,格式YYYYMMDD | 20260516 | +| **课程编号** | 根据班级名称自动匹配 | 如AICODE03-01 | +| **课次** | 根据学期周数自动计算 | 第11周 = 课次11 | +| **课程主题** | 根据课程代码+周数自动匹配 | 如"蜥蜴" | + +**输入示例**: +``` +极简输入: +/课评 班级:发现世界-周四19点 +乔乔:gj5→zd3→zt ↑++ + +自动补全后: +日期:20260516 +班级:发现世界-周四19点 +课程编号:DISC-011 +课次:第11课 +课程主题:蜥蜴 +``` + +### 11.3 路径自动创建(自动启用) + +**功能**:自动创建不存在的目录结构,避免保存失败 + +**自动创建的目录结构**: +``` +.claude/memory/class/ +├── {班级名称}/ +│ ├── summaries/ ← 自动创建 +│ ├── {学生姓名}/ +│ │ └── feedback/ ← 自动创建 +│ └── 补课/ +│ └── {学生姓名}/ +│ └── feedback/ ← 自动创建 +└── .backup/ ← 自动创建 +``` + +### 11.4 速记符号自动补全(输入时提示) + +**功能**:输入速记符号时实时提示含义,Tab键自动补全 + +**速记符号速查表**: +| 符号 | 含义 | 完整描述 | +|------|------|---------| +| `gj` | 观望 | gj5=观望5分钟 | +| `zd` | 主动搭 | zd3=主动搭3层 | +| `zt` | 自己调整 | 球卡住时自己调整高度 | +| `wb` | 完成 | 独立完成搭建 | +| `zx` | 专注 | zx15=专注15分钟 | +| `sb` | 失败后调整 | sb2=失败2次后成功 | +| `ts` | 探索 | ts5=探索5分钟 | +| `cz` | 创造 | cz3=3种创意方案 | +| `wt` | 提问 | wt3=提问3次 | +| `hz` | 合作 | 合作完成 | +| `fx` | 分享 | 分享想法/作品 | + +**自动补全交互示例**: +``` +教师输入:乔乔:gj +系统提示: + ├─ gj3 → 观望3分钟 + ├─ gj5 → 观望5分钟 + └─ gj10 → 观望10分钟 +教师按Tab键:→ gj5 +``` + +### 11.5 实时校验提醒(保存前检查) + +**功能**:保存前自动检查规范,提前发现问题 + +**校验清单**: +| 检查项 | 规范要求 | +|--------|---------| +| **课程编号** | CSP/AICODE前缀,不是C++/AI | +| **日期格式** | YYYYMMDD格式 | +| **目录结构** | 完整路径存在 | +| **文件命名** | 符合规范要求 | +| **课评正文** | 不提及"补课"等词 | +| **字数范围** | 180-350字 | + +**校验指令**: +- `/检查` → 检查本周所有课评 +- `/检查 {班级}` → 检查指定班级课评 + +### 11.6 智能班级预加载(开始工作时) + +**功能**:根据输入的星期几快速预加载对应班级,并展示每个班级的学生名单 + +**快捷指令**: +| 指令 | 功能 | +|------|------| +| **`/周几`** | **按上课日快速索引(推荐)**,如 `/周六`、`/周日`、`/周四` | +| `/今天` | 自动判断当天星期几并加载对应班级 | +| `/本周` | 选择本周班级列表 | +| `/模板 {班级}` | 加载班级学生名单模板 | + +**/周几 输出格式示例**(以 /周六 为例,其他上课日同理): +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +📅 今天是 2026-05-16(周六) +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +班级 1:发现世界-周六09点(DISC) +├─ 学生名单:乔乔、昊昊、小明、小红 +└─ [选择此班级] + +班级 2:Wedo创造世界-周六1030(CREATE) +├─ 学生名单:小强、小芳、小华 +└─ [选择此班级] + +班级 3:AICODE03小Q周六1400(AICODE03) +├─ 学生名单:李明、王芳、张伟、刘洋 +└─ [选择此班级] + +班级 4:Wedo创造世界-周六16点(CREATE) +├─ 学生名单:赵磊、孙悦、周杰 +└─ [选择此班级] + +班级 5:发现世界-周六19点(DISC) +├─ 学生名单:陈静、杨帆、黄欣 +└─ [选择此班级] +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +操作:点击 [选择此班级] 或直接输入班级名称 +``` + +### 11.7 批量处理优化 + +**并行生成+逐份实时保存**: +``` +教师输入5个学生 → 系统并行生成 +→ 乔乔课评生成完成 → 立即保存 ✅ +→ 昊昊课评生成完成 → 立即保存 ✅ +→ 其他继续... +``` + +**批量修改工具**: +- `/批量修改 {查找}→{替换}` → 批量替换本周所有课评内容 +- `/批量添加 {内容}` → 批量在课评结尾添加内容 + +### 11.8 待修复列表功能 + +**位置**:`.claude/.tasks/fix-list-YYYYMMDD.md` + +**查看与修复**: +- 指令:`/修复` → 展示待修复列表,逐个处理或批量自动修复 + +--- + +## 十二、快捷指令完整列表 + +### 班级选择 +| 指令 | 功能 | +|------|------| +| **`/周几`** | **按上课日快速索引(推荐)**,如 `/周六`、`/周日`、`/周四` | +| `/今天` | 自动判断当天星期几并加载对应班级 | +| `/本周` | 选择本周班级列表 | +| `/班级 {班级名}` | 手动选择指定班级 | + +### 模式切换 +| 指令 | 功能 | +|------|------| +| `/交互式` | 启用交互式课评生成模式(默认,Form-First 网页表单) | +| `/批量` | 启用批量输入模式 | + +### 模板工具 +| 指令 | 功能 | +|------|------| +| `/模板 {班级}` | 加载班级学生名单模板 | +| `/空模板` | 创建空模板 | + +### 批量操作 +| 指令 | 功能 | +|------|------| +| `/批量修改 {查找}→{替换}` | 批量替换课评内容 | +| `/批量添加 {内容}` | 批量在课评结尾添加内容 | + +### 数据恢复 +| 指令 | 功能 | +|------|------| +| `/恢复 {学生}` | 恢复该学生的备份 | +| `/恢复备份` | 恢复最近一次备份 | +| `/清理备份` | 清理过期备份文件 | + +### 校验检查 +| 指令 | 功能 | +|------|------| +| `/检查` | 检查本周课评是否符合规范 | +| `/检查 {班级}` | 检查指定班级课评 | + +### 保存与补存 +| 指令 | 功能 | +|------|------| +| `/补存` | 尝试重新保存失败的课评 | +| `/学生 {姓名}` | 查看学生档案和历史课评 | + +### 修复工具 +| 指令 | 功能 | +|------|------| +| `/修复` | 处理待修复列表中的项目 | + +--- + +## 十三、高效课后完整工作流程示例 + +> 以下流程适用于所有上课日(周一~周日),以周六为例展示 + +### Step 1:智能预加载班级 +``` +教师:/周六(或 /今天) +→ 显示周六所有班级 + 学生名单 + 当周课程主题: + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +📅 今天是 2026-05-16(周六,第11周) +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +班级 1:发现世界-周六09点(DISC) +├─ 学生名单:乔乔、昊昊、小明、小红 +├─ 当周课程:DISC-011 蜥蜴 ✅ +└─ [选择此班级] + +班级 2:Wedo创造世界-周六1030(CREATE) +├─ 学生名单:小强、小芳、小华 +├─ 当周课程:CREATE-011 推磨机器人 ✅ +└─ [选择此班级] + +... +``` + +### Step 2:选择班级 → 自动匹配当周课程 + 启动表单服务器 +``` +教师:1(或 发现世界-周六09点) +→ 系统根据日期自动匹配当周课程主题 → 启动本地表单服务器 + +🖥️ 本地服务器已启动! +👉 请打开浏览器:http://localhost:8088/form?class=发现世界-周六09点&week=11&course=DISC-011&theme=鳄鱼&date=2026-05-16 + (表单已预填班级、周数、课程、学生名单) + + 也可在聊天中直接输入(备选): + 乔乔:gj5→zd3→zt ↑++ + 昊昊:慢热→zd3→反复调 → +``` + +### Step 3:网页表单填写 + 直连提交 +``` +教师打开表单 → + ├─ 乔乔:勾选「出勤」→ 输入 gj5→zd3→zt ↑++ + ├─ 昊昊:勾选「出勤」→ 输入 慢热→zd3→反复调 → + ├─ 小明:勾选「请假」 + ├─ 🔄 补课学生:点「+添加临时学生」→ 输入姓名 → 勾选「补课」→ 输入表现 + └─ 点击「🚀 提交并保存」 + +→ 数据自动 POST 到本地服务器 +→ 服务器保存为 .claude/.tmp/evaluation_input_发现世界-周六09点.json +→ 写入信号文件 .claude/.tmp/EVALUATION_READY.txt +→ 表单显示「✅ 已保存 — 可关闭此页面」 +``` + +### Step 4:AI 自动检测 → 生成并双轨保存 +``` +→ AI 检测到 EVALUATION_READY.txt 信号文件 +→ 读取 JSON 数据 → 解析学生/状态/表现 +→ 生成乔乔课评 → 自动保存 ✅ +→ 生成昊昊课评 → 自动保存 ✅ +→ 小明标记为请假 → 记录到班级汇总 +``` + +### Step 5:实时校验提醒 +``` +✅ 乔乔:全部通过 +⚠️ 昊昊:课程编号不规范,建议改为DISC-011 +→ 教师确认修改 → 自动修复后保存 +``` + +### Step 6:检查待修复 +``` +教师:/修复 +→ 查看待修复列表,处理剩余项目 +``` + +### Step 7:完成! +``` +━━━━━━━━━━━━━━━━━━━━━━━━ +✅ 全部完成! +已保存学生:2人 +已备份文件:4份(主文件+备份) +待修复项目:0项 +🗑️ 已自动清理临时表单文件 +━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +--- + +## 十四、交互式课评生成流程(v4.5 直连提交版) + +> **核心理念**:通过 /周几 快速索引 → 启动本地表单服务器 → 浏览器填写直连提交 → AI 自动检测生成 +> **适用场景**:课后按班级处理,交互友好,高效批量,无需粘贴 +> **适用范围**:本流程适用于所有上课日(`/周一`~`/周日`),以下以 `/周六` 为例展示 +> **v4.5 优化**:表单直连提交 — 数据 POST 到本地服务器,AI 通过信号文件自动触发,彻底取消复制粘贴 + +### 完整流程 + +``` +Step 1: 启动 → 输入 /周几(如 /周六、/周四,按当天上课日快速索引) + ↓ +Step 2: 展示该时段班级列表(附带当周课程主题) + ↓ +Step 3: 选择班级 → 自动匹配当周课程 → 启动表单服务器 + ↓ +Step 4: 打开浏览器表单 → 填写学生表现 → 点击「提交并保存」 + ↓ (数据 POST 到本地服务器,保存为 JSON + 写入信号文件) +Step 5: AI 检测信号文件 → 读取 JSON → 批量生成课评 → 双轨保存 + ↓ +Step 6: 🗑️ 自动删除临时文件 → 完成 +``` + +--- + +### Step 1: 启动 — 快速索引 + +**输入指令**(支持两种方式): + +| 指令 | 适用场景 | 示例 | +|:-----|:---------|:-----| +| **`/周几`** | 按上课日快速查找(**推荐**) | `/周六`、`/周日`、`/周四` | +| `/今天` | 自动判断当天是周几 | `/今天`(自动换算为当天对应周几) | + +**工作日对照表**(系统自动根据班级目录匹配): + +| 指令 | 匹配班级示例 | +|:-----|:-------------| +| `/周一`~`/周三` | 按需显示 | +| `/周四` | 发现世界-周四19点 | +| `/周五` | AICODE03小Q周五1900 | +| `/周六` | 发现世界-周六09点、Wedo创造世界-周六1030、AICODE03小Q周六1400 等 | +| `/周日` | 发明世界-周日14点、SPIKE02-周日1030、发现世界-周日下午16点 等 | + +**系统响应**(以教师输入 `/周六` 为例): + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +📅 周六(2026-05-16)的课程 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +班级 1:发现世界-周六09点(DISC) +├─ 学生数:4人(乔乔、昊昊、小明、小红) +└─ [选择此班级] + +班级 2:Wedo创造世界-周六1030(CREATE) +├─ 学生数:3人(小强、小芳、小华) +└─ [选择此班级] + +班级 3:AICODE03小Q周六1400(AICODE03) +├─ 学生数:4人(李明、王芳、张伟、刘洋) +└─ [选择此班级] + +班级 4:Wedo创造世界-周六16点(CREATE) +├─ 学生数:3人(赵磊、孙悦、周杰) +└─ [选择此班级] + +班级 5:发现世界-周六19点(DISC) +├─ 学生数:3人(陈静、杨帆、黄欣) +└─ [选择此班级] +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +请回复班级序号或名称来选择班级(如:1 或 发现世界-周六09点) +``` + +--- + +### Step 2: 选择班级 → 自动匹配当周课程 + 启动服务器 + +> ⚠️ **重要**:以下流程适用于所有上课日。选择任何班级后,系统均自动根据**当周日期匹配课程主题** + 启动本地表单服务器。 + +**教师输入**(任选一种): +``` +1 +``` +或 +``` +发现世界-周六09点 +``` + +**系统响应** — 自动加载课程信息 + 匹配当周课程 + 启动服务器: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +✅ 已选择班级:发现世界-周六09点(DISC) +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +📚 课程信息: +├─ 课程编号:DISC-011 +├─ 课程主题:鳄鱼(第11周自动匹配) +├─ 核心知识点:嘴巴开合、铰链结构、咬合功能 +├─ 日期:20260516 + +👨‍👩‍👧‍👦 学生:乔乔、昊昊、小明、小红(共4人) + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +🖥️ 启动本地表单服务器... +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +👉 请打开浏览器填写表单: + http://localhost:8088/form?class=发现世界-周六09点&week=11&course=DISC-011&theme=鳄鱼&date=2026-05-16 + + (表单已自动填入班级信息、学生名单和课程主题) + + 也可在聊天中直接输入文本(备选模式B): + 乔乔:gj5→zd3→zt ↑++ + 昊昊:慢热→zd3→反复调 → + ... +``` + +**课程自动匹配逻辑**: +1. 根据当前日期计算学期周数(基于3月2日学期开始) +2. 根据周数直接匹配课程代码和主题(参见 `15-semester-weeks.md` 映射表) +3. **不参考上节课进度**,直接使用当周实际课程主题 +4. 仅当教师特别说明补课时,才手动调整课程主题 + +**特殊情况处理**: +- 若当周为补课(教师明确说明),可手动选择补课主题 +- 若无特殊说明,一律使用当周标准课程主题 + +--- + +### Step 3: 网页表单填写(直连提交模式) + +> 选择班级后系统自动启动本地服务器,表单通过 URL 参数传入班级/学生/课程信息。 +> 教师在浏览器中填写表现,点击「提交并保存」后数据直接 POST 到服务器。 + +**表单内容示例**(自动生成,含学生画像摘要): + +``` +┌────────────────────────────────────────┐ +│ 📝 Wedo创造世界-周六1030 课评输入表 │ +│ CREATE-011 · 推磨机器人 · 2026-05-16 │ +├────────────────────────────────────────┤ +│ 📊 填写进度:████████░░ 3/6 人 │ +│ │ +│ ┌─ ① 梁家铭 🧒 ─────────────────┐ │ +│ │ 📋 需鼓励建立自信... │ │ +│ │ 状态:[✅出勤] [🚫请假] │ │ +│ │ 表现:______________________ │ │ +│ │ (速记: gj#观望/zd#搭#层/zt调整) │ │ +│ └────────────────────────────────┘ │ +│ │ +│ ┌─ ② 简思瑜 🧒 ─────────────────┐ │ +│ │ 📋 自信主动,结构搭建极坚固... │ │ +│ │ 状态:[✅出勤] [🚫请假] │ │ +│ │ 表现:______________________ │ │ +│ └────────────────────────────────┘ │ +│ ... │ +│ ┌─ + 添加临时学生 ──────────────┐ │ +│ │ 姓名:[____] 状态:[补课/体验] │ │ +│ └────────────────────────────────┘ │ +│ │ +│ [🚀 提交并保存] │ +└────────────────────────────────────────┘ +``` + +**填写方式**(二选一): + +| 方式 | 操作 | 适用场景 | +|:----|:-----|:---------| +| **A. 网页直连提交(推荐)** | 打开浏览器链接 → 填写 → 点击「提交并保存」→ 数据自动 POST 到服务器 | 常规使用 | +| **B. 聊天文本输入** | 在聊天中直接输入多行文本 | 快速处理、数据量少 | + +**方式A:网页直连提交流程**: +``` +1. 打开系统提供的表单链接(URL 已包含班级/周数/课程/学生) +2. 为每位学生选择状态(出勤/请假/补课/体验) +3. 在文本框中填写表现(支持速记 + 自然语言混合) +4. 点击「🚀 提交并保存」 +5. 看到「✅ 提交成功」提示 → 可关闭页面 +6. AI 自动检测信号文件 → 生成课评 → 双轨保存 +``` + +**方式B:聊天文本输入(备选)**: +``` +乔乔:gj5→zd3→zt ↑++ +昊昊:慢热→zd3→反复调 → +小明 体验 +小红:搭了3层,开心 ↑ +``` + +### Step 4: AI 自动检测信号 + 批量生成并保存 + +**触发方式**:表单提交后服务器写入 `.claude/.tmp/EVALUATION_READY.txt` 信号文件,AI 检测到后自动处理。 + +**系统执行**: +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +🔔 检测到新提交的表单数据 + 班级:发现世界-周六09点 | DISC-011 鳄鱼 + 学生:4人(3人出勤,1人请假) +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +🚀 开始批量生成课评... + +[1/3] 生成乔乔课评... ✅ 已保存 +[2/3] 生成昊昊课评... ✅ 已保存 +[3/3] 生成小红课评... ✅ 已保存 +📝 小明标记为请假,不生成课评 + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +✅ 全部完成! +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +已保存:3人 | 请假:1人 +├─ 班级总结:summaries/20260516_DISC-011_班级反馈.md +└─ 个人课评:乔乔/、昊昊/、小红/ +🗑️ 已清理临时信号文件 + +下一步: +- 继续下一个班级 → 输入 /周几 +- 查看班级总结 → [查看总结] +``` + +--- + +### 快捷操作速查 + +| 操作 | 输入格式 | 效果 | +|:-----|:---------|:------| +| **标记请假** | `{学生} 请假` | 标记缺课,不生成课评 | +| **标记体验** | `{学生} 体验` | 体验标记,仅存班级汇总 | +| **标记补课** | `{学生} 补课` | 补课标记,跨班级自动保存 | +| **恢复出勤** | `{学生} 出勤` | 取消特殊标记,恢复默认出勤 | +| **修改已填** | `修改{学生}:新内容` | 替换该学生已填表现 | +| **添加临时学生** | `添加{姓名}` | 添加到列表末尾 | +| **批量生成** | `全部生成` | 一次性生成所有已填课评 | +| **查看汇总** | `查看汇总` | 查看当前已填写的所有学生 | + +**标记使用示例**: +``` +# 批量填写带标记 +乔乔:gj5→zd3→zt ↑++ +昊昊:慢热→zd3→反复调 → +小明 体验 +小红 请假 +小华[补课]:专注完成,情绪稳定 ↑ + +# 修改已填表现 +修改乔乔:gj5→zd3↑↑ + +# 调整学生标记 +小明 出勤(恢复为正式学生) +``` + +--- + +## 十五、工作流模式选择 + +### 两种模式对比 + +| 模式 | 特点 | 适用场景 | +|------|------|---------| +| **交互式模式** | `/周几` 快速索引 + Form-First 网页表单(含补课/体验区)+ 一键提交 | 课后按班级处理,高效友好 | +| **批量输入模式** | 一次性输入所有学生 | 已有记录,速度优先 | + +### 模式切换 + +``` +/交互式 → 启用交互式模式(默认) +/批量 → 启用批量输入模式 +``` + +--- + +*版本:v4.5(表单直连提交 — 取消复制粘贴,数据直通 AI)* +*最后更新:2026-05-20* +*优化技能:keping-optimizer* diff --git a/.claude/rules/21-shorthand.md b/.claude/rules/21-shorthand.md index 6c8045d..7524cb8 100644 --- a/.claude/rules/21-shorthand.md +++ b/.claude/rules/21-shorthand.md @@ -1,7 +1,10 @@ # 速记符号系统 > 从 20-workflow.md 拆分,专注速记符号定义与使用规则 -> 版本:v3.1 | 更新日期:2026-05-05 +> 版本:v4.5 | 更新日期:2026-05-20 +> +> **v4.5 变更**:表单直连提交 — 取消复制粘贴,版本号同步 +> **v4.4 变更**:统一版本号至 v4.4;更新日期 --- diff --git a/.claude/rules/22-student-mgmt.md b/.claude/rules/22-student-mgmt.md index 328a566..31373fc 100644 --- a/.claude/rules/22-student-mgmt.md +++ b/.claude/rules/22-student-mgmt.md @@ -1,7 +1,12 @@ # 学生特殊处理:补课、新学生、转正 > 从 20-workflow.md 拆分,专注补课/体验/新学生/转正规则 -> 版本:v4.0 | 更新日期:2026-05-14 +> 版本:v4.5 | 更新日期:2026-05-20 +> +> **v4.5 变更**:简化补课存储规则 — 取消补课专用目录和双向记录,补课记录统一保存在学生原班级,文件名加 `_补课` 后缀 +> **v4.4 变更**:统一版本号至 v4.4;更新日期 +> **v4.2 变更**:统一禁用"今天";删除示例中禁止的时间表述 +> **v4.1 变更**:新增表单补课区入口说明 — 补课/体验学生可通过网页表单的「补课/体验学生区」录入 > > **v4.0 变更**:同步课评规范V1.0 — 新增补课双向记录规则;更新存储路径为 `.claude/memory/class/` 标准结构;新增补课目录 `补课/` 专用路径 @@ -11,12 +16,15 @@ ### 1.1 核心规则 -**绝对禁止**:课评正文中绝对不能提及学生来补课相关内容。 +**录入入口**:补课/体验学生可通过 [网页表单的「补课/体验学生区」](20-workflow.md#step-3-网页表单填写form-first-模式) 录入(选择班级后自动创建),也可在聊天中直接输入 `姓名 [补课]` 格式。 + +**绝对禁止**:课评正文(给家长看的部分)绝对不能提及学生来补课相关内容。 - ❌ 禁止出现"补课"、"补课上"、"来补课"、"本次补课" -- ❌ 禁止暗示学生非正常上课("今天特别来参加"、"临时加入"、"从其他班级过来") +- ❌ 禁止暗示学生非正常上课("本节课特别来参加"、"临时加入"、"从其他班级过来") - ✅ 课评正文完全按正常学生撰写 - ✅ `[补课]`标记仅用于后台档案管理 +- ✅ 文件开头元信息可以标注补课来源(如"(补课,来自 AICODE06洋芋周日1400)"),不影响家长阅读的正文内容 **示例**: @@ -29,10 +37,10 @@ 课评输出(错误): 小红本节课作为补课学生,学习了"旋转飞机"... ❌ -小红今天来补课,学习了"旋转飞机"... ❌ +小红来补课,学习了"旋转飞机"... ❌ ``` -### 1.2 补课学生分类处理 +### 1.2 补课学生分类处理(v4.5更新) **情况A:自己班级的学生补课** - **判断**:学生在 `.claude/memory/class/{当前班级}/` 目录中存在 @@ -40,9 +48,10 @@ **情况B:跨班级补课(档案在其他班级)** - **判断**:学生在 `.claude/memory/class/{其他班级}/` 目录中存在 -- **处理**:自动跨班级保存(课评规范标准) - - ✅ 课评文件保存到补课班级的 `补课/{学生名}/feedback/YYYYMMDD_课程编号.md` - - ✅ 原班级侧生成补课追踪文件 `feedback/YYYYMMDD_课程编号-课次(补课-去班级名).md` +- **处理**:课评文件保存到学生原班级的 `feedback/YYYYMMDD_课程编号-课次_补课.md` + - ✅ 文件名加 `_补课` 后缀,一眼识别 + - ✅ 文件内容开头标注补课信息(补课时间、补课班级) + - ✅ 课评正文正常撰写,不提及补课 - **无需询问,自动完成** **情况C:其他老师班级补课学生** @@ -51,7 +60,7 @@ - [1] 保存到补课班级的 `补课/{学生名}/feedback/`(仅班级记录) - [2] 创建新档案(在本班建立 `profile.md`) -### 1.3 跨班级补课示例 +### 1.3 跨班级补课示例(v4.5更新) ``` 教师输入:班级:发现世界-周六09点,林瀚丞[补课]:积极分析课程任务,专注完成了绿色身体、黑色头部的蜥蜴设计 @@ -62,11 +71,14 @@ AI检测: 判断:跨班级补课学生(原班级周四19点,补课班级周六09点) -自动处理(课评规范标准): -→ 补课班级侧:保存到「补课/林瀚丞/feedback/YYYYMMDD_DISC-008.md」 - (内容开头注明"(补课,来自 发现世界-周四19点)") -→ 原班级侧:保存到「林瀚丞/feedback/YYYYMMDD_DISC-008(补课-去发现世界-周六09点).md」 - (简要记录补课去向) +自动处理(v4.5简化规则): +→ 保存到原班级:「林瀚丞/feedback/YYYYMMDD_DISC-008_补课.md」 + 文件内容开头标注: + - 课程代码:DISC-008 + - 课程主题:蜥蜴 + - 补课班级:发现世界-周六09点 + - 补课时间:周日 09:00 + (正文正常撰写,不提及补课) ``` --- @@ -116,32 +128,90 @@ AI检测: --- -## 四、课评规范V1.0补课记录要求 +## 四、补课存储规则(v4.5更新) -### 4.1 补课目录结构 +### 4.1 新规则核心变更 + +| 版本 | 存储方式 | 说明 | +|------|---------|------| +| v4.4及以前 | 双向记录 + 补课专用目录 | 原班级和补课班级各存一份,创建`补课/`目录 | +| **v4.5** | **单记录 + 原班级保存** | **只保存在学生原班级,文件名加`_补课`后缀** | + +### 4.2 v4.5存储结构 + +``` +.claude/memory/class/{学生原班级}/ +├── 学生姓名/ +│ ├── profile.md +│ ├── summary/ +│ │ └── 成长素材.md +│ └── feedback/ +│ ├── 20260419_DISC-007.md ← 正常上课 +│ ├── 20260505_DISC-009_补课.md ← 补课记录(文件名加后缀) +│ └── 20260509_DISC-010(请假).md +``` + +### 4.3 补课文件格式 + +**文件名**:`YYYYMMDD_课程编号-课次_补课.md` + +**文件内容**: +```markdown +# DISC-009 课评 + +**日期**: 2026-05-05 + +**课评内容**: + +- 课程代码:DISC-009 +- 课程主题:机器人瓦力 +- 补课班级:周日9:00(补课班级) +- 原班级:发现世界-周六09点 + +嘉铭本节课学习了"机器人瓦力"... +(正文正常撰写,不提及补课) + +**教师备注**: +- 亮点: +- 需关注: +- 确认状态:☑ 已确认(2026-05-05) +``` + +### 4.4 规则优势 + +- ✅ **学生所有记录在一个文件夹**:方便查看完整学习轨迹 +- ✅ **一眼识别补课记录**:通过 `_补课` 后缀区分 +- ✅ **避免临时班级目录**:不再创建 `周日9点` 等补课专用班级 +- ✅ **简化存储结构**:取消双向记录,减少文件冗余 + +--- + +## 五、历史规则存档(v4.4及以前) + +> 以下规则已于 v4.5 废弃,仅作参考 + +### 5.1 已废弃:补课目录结构(v4.4) ``` .claude/memory/class/{补课班级}/ ├── 学生姓名/ ← 正式学生 │ └── feedback/ -│ └── YYYYMMDD_课程编号.md -└── 补课/ ← 补课学生专用 +│ └── YYYYMMDD_课程编号-课次.md +└── 补课/ ← 补课学生专用(已废弃) └── {学生姓名}/ └── feedback/ - └── YYYYMMDD_课程编号.md + └── YYYYMMDD_课程编号-课次.md ``` -### 4.2 双向记录 +### 5.2 已废弃:双向记录(v4.4) **补课产生两条文件记录**: | 位置 | 文件名 | 内容 | |------|--------|------| -| 原班级侧 | `feedback/YYYYMMDD_课程编号-课次(补课-去班级名).md` | 记录"去了哪补课" | -| 补课班级侧 | `补课/{学生}/feedback/YYYYMMDD_课程编号.md` | 正常课评,开头注明来源 | +| 原班级侧 | `feedback/YYYYMMDD_课程编号-课次(补课-去班级名).md` | 记录"去了哪补课",无正文 | +| 补课班级侧 | `补课/{学生}/feedback/YYYYMMDD_课程编号-课次.md` | 正常课评,文件开头注明来源 | -### 4.3 自动化统计影响 +--- -- 补课学生必须在补课班级的 `补课/` 目录下有课评文件 -- 原班级侧的 `(补课-去...).md` 文件用于标记出勤状态(补课=到课) -- 系统三级查找的第二级会搜索所有 `补课/` 目录 +*规则版本:v4.5 | 更新日期:2026-05-20* diff --git a/.claude/rules/30-student.md b/.claude/rules/30-student.md index 2787885..a7eeb34 100644 --- a/.claude/rules/30-student.md +++ b/.claude/rules/30-student.md @@ -1,7 +1,12 @@ # 学生管理规则:画像建立、千人千面、姓名处理 > 合并文件:班级差异与千人千面 + 学生画像建立指南 + 姓名处理规则 -> 版本:v4.0 | 更新日期:2026-05-14 +> 版本:v4.5 | 更新日期:2026-05-20 +> +> **v4.5 变更**:表单直连提交 — 取消复制粘贴;版本号同步 +> **v4.4 变更**:统一版本号至 v4.4;更新日期 +> **v4.2 变更**:统一禁用"今天",统一使用"本节课";修复所有示例中的时间表述 +> **v4.1 变更**:补充补课/体验学生录入说明 — 可通过网页表单「补课/体验学生区」或聊天输入 `姓名 [补课]`/`姓名 [体验]` 录入 > > **v4.0 变更**:同步课评规范V1.0 — 更新档案存储路径为 `.claude/memory/class/` 标准;学生画像文件改为固定名 `profile.md` @@ -167,9 +172,9 @@ Step 6: 持续更新成长轨迹 | 班级类型 | 课评侧重 | 示例 | |---------|---------|------| -| 年龄偏小班 | 参与度、情绪适应 | "今天能主动拿起管道尝试,这个开始很重要" | +| 年龄偏小班 | 参与度、情绪适应 | "本节课能主动拿起管道尝试,这个开始很重要" | | 能力较强班 | 创意、挑战度 | "不仅完成基础搭建,还自己加了弯管设计" | -| 活跃好动班 | 专注力、规则意识 | "今天专注了15分钟,中途没有离开座位" | +| 活跃好动班 | 专注力、规则意识 | "本节课专注了15分钟,中途没有离开座位" | | 内向安静班 | 社交互动、表达 | "主动邀请旁边的小朋友一起看球滚落" | ### 3.2 学生维度差异 @@ -181,15 +186,15 @@ Step 6: 持续更新成长轨迹 小明(谨慎型): → 课评侧重:主动尝试的勇气 -"小明今天观察了5分钟后主动拿起管道,这个开始的勇气比作品本身更值得关注" +"小明本节课观察了5分钟后主动拿起管道,这个开始的勇气比作品本身更值得关注" 小红(活跃型): → 课评侧重:专注和坚持 -"小红今天专注搭建15分钟,没有频繁换玩法,这个坚持很难得" +"小红本节课专注搭建15分钟,没有频繁换玩法,这个坚持很难得" 小强(敏感型): → 课评侧重:抗挫和情绪管理 -"今天球卡住了小强没有急,而是调整了入口高度,这个调整值得肯定" +"本节课球卡住了小强没有急,而是调整了入口高度,这个调整值得肯定" ``` ### 3.3 历史对比差异 @@ -252,4 +257,4 @@ TUBE-001 小小班A班 - **profile.md(标准)**:`.claude/memory/class/{班级}/{学生名}/profile.md` - **标准课评模板**:详见 [20-workflow.md 第7.7节](20-workflow.md) -- **课评规范全文**:[20-workflow.md 第10节](20-workflow.md) 课评规范V1.0对照 +- **课评规范全文**:[20-workflow.md 第10节](20-workflow.md) 课评规范V1.0对照 \ No newline at end of file diff --git a/.claude/rules/50-output-format-preschool.md b/.claude/rules/50-output-format-preschool.md index 2371a66..81b1dc2 100644 --- a/.claude/rules/50-output-format-preschool.md +++ b/.claude/rules/50-output-format-preschool.md @@ -1,11 +1,19 @@ # 课评输出格式规则 - 学龄前版(2.5-6岁) -> 适用课程:意识世界(托班)、发现世界(小班)、发明世界(中班)、创造世界(大班) -> 特点:微信表情增强互动性,温暖亲切,画面感强 -> **重要**:学期周数仅用于后端匹配课程主题,**课评正文不提及"第几周"** -> +> 适用课程:意识世界(托班)、发现世界(小班)、发明世界(中班)、创造世界(大班) +> 版本:v5.0 | 更新日期:2026-05-22 +> +> **v5.0 变更**:统一版本号体系到 v5.0;优化课评详细程度,增加时间描述模糊化规范,AI 自动扩展细节 +> - 标准版字数上限扩展到300字,详细版扩展到400字 +> - 幼儿时间描述采用模糊化表达("一会儿"、"一阵子"、"挺长时间") +> - AI 基于学生画像和历史数据自动补充过程细节和纵向对比 +> **v4.5 变更**:表单直连提交 — 取消复制粘贴,版本号同步 +> **v4.4 变更**:添加版本头,统一版本号至 v4.4 +> 特点:微信表情增强互动性,温暖亲切,画面感强 +> ⚠️ **重要**:学期周数仅用于后端匹配课程主题,课评正文不提及"第几周"、"本周"、"今天" +> ⚠️ **关键规则**:统一使用"本节课",禁用"今天"、"本周"等 > **首次上课/补课说明**:详见 [20-workflow.md](20-workflow.md)(第3节、第7节) -> +> **补课/体验标记**:补课学生输出格式为 "姓名 [补课]",体验学生为 "姓名 [体验]",系统自动识别处理 > **存储位置**(课评规范标准): > - **个人课评文件**:`.claude/memory/class/{班级}/{学生名}/feedback/YYYYMMDD_课程编号-课次.md` > - **班级总结**:`.claude/memory/class/{班级}/summaries/YYYYMMDD_课程编号-课次_班级反馈.md` @@ -20,7 +28,8 @@ - **段落简短**:每段1-2句话,易于阅读 - **画面感强**:描述作品细节,让家长能想象出画面 - **三维度覆盖**:课程设计、学习表现、兴趣度 -- **称呼规范**:优先使用小名/昵称,其次去姓称名(如"昕乔"),禁用"宝贝"等套话 +- **称呼规范**:优先使用小名/昵称,其次去姓称名(如"昕乔"),禁用"宝贝"、"小朋友"等套话 +- **措辞统一**:禁用"今天",使用"本节课" ### 排版样式(三段式) ``` @@ -28,30 +37,30 @@ 这节课【称呼】【整体表现描述】。【掌握程度】,【课程环节表现】。和【对比时间】相比,【进步表现】,【具体亮点】 💪✨ -【课后建议】,【具体做法】 🏠 +【课后建议】,【具体做法】,巩固本节课的【知识点】 🏠 ``` --- ## 📝 三段式结构模板 -> **详细规范**:三段式结构、字数弹性规则、Emoji使用规范参见 [10-style.md](10-style.md)(第2-4节) -> +> **详细规范**:三段式结构、字数弹性规则、Emoji使用规范详见 [10-style.md](10-style.md)(第2-4节) +> > 本文档仅保留学龄前版的**排版样式**和**具体示例** ### 结构速查 | 段落 | 内容 | 字数范围 | Emoji数量 | 推荐表情 | -|------|------|:--------:|:---------:|:-------:| +|------|------|:-------:|:---------:|:-------:| | **第1段** | 课程知识点 | 30-55字 | 1个 | 🔍/💡自动适配 | -| **第2段** | 课堂细节(掌握+环节+亮点)| **100-220字(弹性)** | 1-3个 | 根据情节自动适配 | +| **第2段** | 课堂细节(掌握程度+环节表现+成长亮点)| **100-220字(弹性)** | 1-3个 | 根据情节自动适配 | | **第3段** | 课后建议 | 30-55字 | 1个 | 🏠自动适配 | **段落控制**:全文控制在**3个段落**,第2段为长段落整合多个模块内容 --- -### 第1段:课程知识点(30-40字) +### 第1段:课程知识点(30-55字) **写什么**:本节课的核心结构知识或技能点,体现课程趣味性 **写法**: @@ -66,7 +75,7 @@ **示例**: ``` -小明今天学习了"互锁结构"——把积木像砌墙一样交错叠放,这样搭出来的墙更稳固 🔍 +小明本节课学习了"互锁结构"——把积木像砌墙一样交错叠放,这样搭出来的墙更稳固 🔍 ``` **表情备选**:🔍💡📚⭐ @@ -80,39 +89,39 @@ - 掌握程度:学生对该知识点的学习表现 - 课程环节:导入、探索、实践、分享各环节的状态 - 成长亮点:与之前相比的进步或突出表现 -- **弹性原则**:当输入中有多个亮点或精彩瞬间时,**充分展开描述,不要压缩到100-130字**,可扩展到150-220字 +- **弹性原则**:当输入中有多个亮点或精彩瞬间时,充分展开描述,不要压缩到100-130字,可扩展到150-220字 **格式**: ``` -这节课【孩子称呼】【整体状态描述】。【掌握程度描述】,【课程环节表现】。和【对比时间】相比,【进步表现】,【具体亮点】 💪✨ +这节课【孩子称呼】【整体表现描述】。【掌握程度描述】,【课程环节表现】。和【对比时间】相比,【进步表现】,【具体亮点】 💪✨ ``` **示例**: ``` -这节课小明对房子主题很感兴趣,搭建环节专注投入约30分钟。互锁的方法听懂了,实际操作时前两块需要老师扶着手指对齐,第三块开始能自己完成。和上周比,今天结构倒了没有发脾气,而是拆开重新观察了一下底座平不平,这个调整值得注意 💪✨ +这节课小明对房子主题很感兴趣,搭建环节专注投入约30分钟💪。互锁的方法听懂了,实际操作时前两块需要老师扶着手指对齐,第三块开始能自己完成✨。和上周比,本节课结构倒了没有发脾气,而是拆开重新观察了一下底座平不平,这个调整值得注意🌟 ``` **表情备选**:💪✨🌱📈🎯 --- -### 第3段:课后建议(30-50字) +### 第3段:课后建议(30-55字) **写什么**:家长可以在家配合的具体活动,巩固兴趣和学习成果 **写法**: - 可操作:不说"多练习",说具体玩法 -- 关联课程:在家可以用积木重复今天的互锁结构 +- 关联课程:"在家可以用乐高重复本节课的互锁结构" - 尊重家庭:用"可以试试看"而非"必须" -- **弹性原则**:当第2段非常详细时,建议部分也可适度扩展到40-50字,给出更具体的家庭活动建议 +- **弹性原则**:当第2段非常详细时,建议部分也可适度扩展到40-55字,给出更具体的家庭活动建议 **格式**: ``` -【家庭活动建议】,【具体做法】,巩固今天的【知识点】 🏠 +【家庭活动建议】,【具体做法】,巩固本节课的【知识点】 🏠 ``` **示例**: ``` -家里如果有积木,可以和孩子一起搭两堵墙,一堵直着叠、一堵交错叠,推推看哪个更稳,巩固今天的互锁概念 🏠 +家里如果有积木,可以和孩子一起搭两堵墙,一堵直着叠、一堵交错叠,推推看哪个更稳,巩固本节课的互锁概念 🏠 ``` **表情备选**:🏠👨‍👩‍👧🎮📱 @@ -123,51 +132,69 @@ ## 📊 完整示例 -### 示例1:小班-发现世界(三段式) +### 示例1:小班-发现世界(标准版)- v4.6 更新 +**输入**:小明:观望一会儿→主动搭3层→自己调整 ↑++ + +**输出**: ``` -小明今天学习了"互锁结构"——把积木像砌墙一样交错叠放,这样搭出来的墙更稳固🔍 +小明本节课学习了"互锁结构"——把积木像砌墙一样交错叠放,这样搭出来的墙更稳固,不容易倒🔍 -这节课小明对房子主题很感兴趣,搭建环节专注投入约30分钟💪。互锁的方法听懂了,实际操作时前两块需要老师扶着手指对齐,第三块开始能自己完成✨。导入环节参与积极,分享时能说出互锁的作用,本节课的结构搭建目标顺利达成🌟。和上周比,今天结构倒了没有发脾气,而是拆开重新观察了一下底座平不平,这个调整值得注意📈 +本节课小明对房子主题表现出浓厚兴趣,开始阶段先观察了一会儿,后来在老师鼓励下主动开始搭建,专注投入了挺长时间💪。互锁的方法听懂了,实际操作时前两块需要老师扶着手指对齐凹槽,第三块开始能独立完成,到第五块时已经能自己检查是否对齐✨。结构第一次倒了是因为底座不平,小明没有像以前那样直接推倒重来,而是拆开重新观察底座,发现左边比右边低,调整后重新搭建,这个情绪调节和问题解决能力比两周前有明显提升🌟 -家里如果有积木,可以和孩子一起搭两堵墙,一堵直着叠、一堵交错叠,推推看哪个更稳,巩固今天的互锁概念🏠 +家里如果有积木,可以和孩子一起搭两堵墙,一堵直着叠、一堵交错叠,推推看哪个更稳,巩固本节课的互锁概念🏠 ``` -**字数**:198字(符合180-220) -**表情数**:5个(第1段1个/第2段3个/第3段1个),第2段表情分散在段内 +**字数**:258字(符合220-300字标准版) +**表情数**:4个(第1段1个/第2段2个/第3段1个),第2段分散在段内 **段落数**:3段(符合要求) +**v4.6 改进点**: +- 时间描述模糊化("观察了一会儿"、"挺长时间"而非精确分钟数) +- 增加过程细节(第2块→第3块→第5块的进步阶梯) +- 增加思维描述(发现左边比右边低) +- 增加纵向对比(两周前的情绪调节能力) +- AI 自动扩展了画像和历史数据中的细节 + --- -### 示例2:托班-意识世界(三段式) +### 示例2:托班-意识世界(标准版)- v4.6 更新 +**输入**:昀昊:害羞→搭2层管道 ↑ + +**输出**: ``` 昀昊本节课玩了"管道滚球",让小球在管道里旅行,感受了球滚动的乐趣🔍 -本节课昀昊开始有点害羞,看了2分钟才开始尝试,后来在老师鼓励下搭了2层管道让小球滚下来💪。导入环节对滚球游戏很感兴趣,探索环节专注尝试管道连接,最后能独立完成2层搭建,本节课的管道连接目标顺利达成🌟。和上周相比,本节课敢自己拿管道尝试了,不再只是看着,能安静专注地玩10分钟,这个专注力对托班宝宝来说很棒了✨ +本节课昀昊开始有点害羞,先观察了一会儿才开始尝试,后来在老师鼓励下搭了2层管道让小球滚下来💪。导入环节对滚球游戏很感兴趣,探索环节专注尝试管道连接,最后能独立完成2层搭建,本节课的管道连接目标顺利达成✨。和上周比,本节课敢自己拿管道尝试了,不再只是看着,能安静专注地玩一阵子,这个专注力对托班宝宝来说很棒了🌟 -爸爸妈妈可以用保鲜膜筒芯或报纸卷成管道,和小球一起玩,让球从高的地方滚下来,感受运动的快乐🏠 +家里可以用保鲜膜筒芯或报纸卷成管道,和小球一起玩,让球从高的地方滚下来,感受运动的快乐🏠 ``` -**字数**:195字(符合180-220) -**表情数**:5个(第1段1个/第2段3个/第3段1个),第2段表情分散在段内 +**字数**:198字(符合180-220字精简版-标准版之间) +**表情数**:3个(第1段1个/第2段2个/第3段1个),第2段分散在段内 **段落数**:3段(符合要求) **语气**:更温和,适合托班 +**v4.6 改进点**: +- 时间描述更模糊("观察了一会儿"、"一阵子"而非"2分钟"、"10分钟") +- 保持托班适用的温和语气 +- AI 自动补充了情绪变化细节 + --- ## ⚙️ 技术规范 -### 字数控制(弹性范围) +### 技术规范(弹性范围)- v4.6 更新 -| 输入类型 | 字数范围 | 适用场景 | -|:-------:|:-------:|:---------| -| **精简版** | 180-220字 | 输入简洁,仅包含基本行为描述 | -| **标准版** | 220-280字 | 输入有具体细节或1-2个亮点 | -| **详细版** | 280-350字 | 输入有精彩瞬间、多个亮点或特殊表现 | +| 输入类型 | 字数范围 | 适用场景 | 结构 | +|:-------:|:-------:|:---------|:----:| +| **精简版** | 180-220字 | 输入简洁,仅包含基本行为描述 | 3段 | +| **标准版** | 220-300字 | 输入有具体细节或1-2个亮点 | 3段 | +| **详细版** | 300-400字 | 输入有精彩瞬间、多个亮点或特殊表现 | 3-4段 | **各年龄段参考**: -- 托班(2.5-3岁):可适当减少20-30字 +- 托班(2.5-3岁):可适当减少20-30字,时间描述更模糊 - 小班(3-4岁):按标准范围 - 中班(4-5岁):按标准范围 - 大班(5-6岁):可适当增加10-20字 @@ -177,7 +204,9 @@ - **标准版**:输入有具体细节或1-2个亮点(如"主动搭3层,自己调整,还帮助同伴") - **详细版**:输入有精彩瞬间、多个亮点或特殊表现(如"第一次主动帮助同伴,调试了三次才成功,最后说这是最喜欢的作品") -### 表情数量 +**AI 自动扩展**:即使老师输入简洁,AI 也会基于学生画像和历史数据自动补充细节,生成更丰富的课评 + +### Emoji数量 - **第1段**:1个(🔍/💡根据课程主题适配) - **第2段**:1-3个(根据课堂情节亮点自动适配,如💪/✨/📈等) - **第3段**:1个(🏠/👨‍👩‍👧根据建议内容适配) @@ -190,13 +219,13 @@ **第2段分散示例**: ``` -这节课小明对房子主题很感兴趣,搭建环节专注投入约30分钟💪。互锁的方法听懂了,实际操作时前两块需要老师扶着手指对齐,第三块开始能自己完成✨。和上周比,今天结构倒了没有发脾气,而是拆开重新观察了一下底座平不平,这个调整值得注意🌟。 +这节课小明对房子主题很感兴趣,搭建环节专注投入约30分钟💪。互锁的方法听懂了,实际操作时前两块需要老师扶着手指对齐,第三块开始能自己完成✨。和上周比,本节课结构倒了没有发脾气,而是拆开重新观察了一下底座平不平,这个调整值得注意🌟 ``` ### Emoji适配指南 | 段落 | 内容 | 推荐表情 | 适配场景 | -|------|------|:-------:|---------| +|------|------|:-------:|:---------| | 第1段 | 课程知识点 | 🔍/💡 | 🔍探索新知识/💡有启发 | | 第2段 | 课堂细节 | 1-3个 | 💪努力/✨亮点/📈进步/🌟突破/😊开心 | | 第3段 | 课后建议 | 🏠/👨‍👩‍👧 | 🏠家庭活动/👨‍👩‍👧亲子互动 | @@ -223,23 +252,36 @@ ### 学龄前版专项检查 - [ ] 字数符合弹性范围(精简版180-220字/标准版220-280字/详细版280-350字,根据输入内容丰富度) - [ ] **3段式结构**(第1段知识点、第2段课堂细节、第3段课后建议) -- [ ] 第1段和第3段末尾各有1个emoji;第2段emoji分散在段内,紧跟对应亮点的句号之后(总计3-5个) +- [ ] 第1段和第3段末尾各1个emoji;第2段emoji分散在段内,紧跟对应亮点的句号之后(总计3-5个) - [ ] 表情根据情节自动适配,不机械固定 - [ ] 称呼正确(小名>去姓>叠字>全名) -- [ ] 无"第几周"字样 +- [ ] **无"今天"、"本周"、"第几周"等表述,统一使用"本节课"** - [ ] 语气温暖亲切,有画面感 - [ ] 建议具体可操作 - [ ] **第2段充分展现输入中的精彩瞬间**(不压缩丰富内容) --- +## 📋 班级总结模板 + +班级总结文件(`summaries/YYYYMMDD_课程编号-课次_班级反馈.md`)使用统一模板框架,完整模板定义详见 [20-workflow.md 第5.4节](20-workflow.md)。 + +### 学龄前版关键要点 + +- **基本信息字段**:表现标签提炼3-5个关键词(如"积极搭建"、"创意设计"、"情绪调节快"),体现本节课核心亮点 +- **情绪状态**:综合判断本节课情绪基调("开心/稳定"、"积极/稳定"、"波动"等) +- **教师备注-亮点**:提炼1-2个最有代表性的亮点描述 +- **本周表现分布**:根据学生实际表现评估填写 +- **共性观察**:重点描述学龄前学生的参与度和兴趣表现 + +--- + ## 📝 与小学版对比 -| 维度 | 学龄前版(本文件)| 小学版 | -|------|------------------|--------| -| **表情** | 3-5个(第1段1个/第2段1-3个/第3段1个),温暖活泼 | 3-5个(第1段1个/第2段1-3个/第3段1个),简洁专业 | -| **段落** | **3段**(第1段知识点、第2段课堂细节、第3段课后建议)| 3段,结构化 | -| **语气** | 亲切温暖,画面感 | 尊重平等,专业 | -| **字数** | 弹性范围180-350字 | 弹性范围190-350字 | -| **信息密度** | 第2段为长段落,根据输入丰富度灵活扩展 | 结构化呈现,根据输入灵活扩展 | -| **emoji位置** | 第1段末尾、第2段分散在段内、第3段末尾 | 第1段末尾、第2段分散在段内、第3段末尾 | +| 维度 | 学龄前版 | 小学版 | +|------|:--------:|:-------:| +| **表情** | 3-5个(第1段1个/第2段1-3个/第3段1个),温暖活泼 | 3-5个,简洁专业 | +| **段落** | 3段(统一三段式) | 3段(统一三段式) | +| **语气** | 温暖亲切,画面感强 | 尊重平等,专业简洁 | +| **字数** | 弹性范围180-350字 | 弹性范围180-350字 | +| **emoji位置** | 第1段末尾、第2段分散在段内、第3段末尾 | 第1段末尾、第2段分散在段内、第3段末尾 | \ No newline at end of file diff --git a/.claude/rules/51-output-format-elementary.md b/.claude/rules/51-output-format-elementary.md index ca21cae..98a15b7 100644 --- a/.claude/rules/51-output-format-elementary.md +++ b/.claude/rules/51-output-format-elementary.md @@ -1,11 +1,19 @@ # 课评输出格式规则 - 小学版(6-10岁) > 适用课程:SPIKE(一年级)、AICODE03(四年级) +> 版本:v5.0 | 更新日期:2026-05-22 +> +> **v5.0 变更**:统一版本号体系到 v5.0;优化课评详细程度,增加过程可视化规范,AI 自动扩展细节 +> - 标准版字数上限扩展到300字,详细版扩展到400字 +> - 强调调试过程、思维转变、数据对比的描述 +> - AI 基于学生画像和历史数据自动补充技术细节和纵向对比 +> **v4.5 变更**:表单直连提交 — 取消复制粘贴,版本号同步 +> **v4.4 变更**:添加版本头,统一版本号至 v4.4 > 特点:专业简洁,尊重平等,准确使用术语但不堆砌 -> **重要**:学期周数仅用于后端匹配课程主题,**课评正文不提及"第几周"、"第几课"等序号** -> +> ⚠️ **重要**:学期周数仅用于后端匹配课程主题,课评正文不提及"第几周"、"本周"、"今天" +> ⚠️ **关键规则**:统一使用"本节课",禁用"今天"、"本周"、"第几周"等 > **首次上课/补课说明**:详见 [20-workflow.md](20-workflow.md)(第3节、第7节) -> +> **补课/体验标记**:补课学生输出格式为 "姓名 [补课]",体验学生为 "姓名 [体验]",系统自动识别处理 > **存储位置**(课评规范标准): > - **个人课评文件**:`.claude/memory/class/{班级}/{学生名}/feedback/YYYYMMDD_课程编号-课次.md` > - **班级总结**:`.claude/memory/class/{班级}/summaries/YYYYMMDD_课程编号-课次_班级反馈.md` @@ -16,16 +24,17 @@ ## 整体风格定位 ### 核心特点 -- **专业简洁**:准确使用编程术语(循环、条件、传感器),不堆砌 -- **尊重平等**:像对待小学习者一样,不居高临下 +- **专业简洁**:准确使用编程术语(循环、条件、事件),但不堆砌 +- **尊重平等**:像对待小学习者一样尊重,不居高临下 - **启发性**:指出问题同时给方向 - **具体性**:不说"很棒",说"自己检查出少了一个结束括号" - **称呼规范**:优先使用小名/昵称,其次去姓称名(如"昕乔"),禁用"宝贝"、"小朋友"等套话 +- **措辞统一**:禁用"今天"、"本周",统一使用"本节课" ### 与学龄前版的语气差异 | 维度 | 学龄前版 | 小学版 | -|------|---------|--------| +|------|:--------:|:-------:| | **语气** | 温暖亲切,画面感强 | 专业简洁,尊重平等 | | **禁用词** | 宝贝、小天才 | 小天才、未来的程序员、秒杀同龄人 | | **术语** | 避免专业术语 | 准确使用但不堆砌 | @@ -35,36 +44,20 @@ ## 三段式结构模板 -> **详细规范**:三段式结构、字数弹性规则、Emoji使用规范参见 [10-style.md](10-style.md)(第2-4节) -> +> **详细规范**:三段式结构、字数弹性规则、Emoji使用规范详见 [10-style.md](10-style.md)(第2-4节) +> > 本文档仅保留小学版的**语气风格**和**具体示例** ### 结构速查 | 段落 | 内容 | 字数范围 | Emoji数量 | 推荐表情 | -|------|------|:--------:|:---------:|:-------:| +|------|------|:-------:|:---------:|:-------:| | **第1段** | 课程知识点 | 30-55字 | 1个 | 💡/⚙️/🤖自动适配 | -| **第2段** | 课堂细节(掌握+环节+亮点)| **100-220字(弹性)** | 1-3个 | 根据情节自动适配 | +| **第2段** | 课堂细节(掌握程度+环节表现+成长亮点)| **100-220字(弹性)** | 1-3个 | 根据情节自动适配 | | **第3段** | 课后建议 | 30-55字 | 1个 | 🏠/🔧自动适配 | **段落控制**:全文控制在**3个段落**,第2段为长段落整合多个模块内容 -### 字数弹性规则 - -| 输入类型 | 字数范围 | 适用场景 | -|:-------:|:-------:|:---------| -| **精简版** | 180-220字 | 输入简洁,仅包含基本行为描述 | -| **标准版** | 220-280字 | 输入有具体细节或1-2个亮点 | -| **详细版** | 280-350字 | 输入有精彩瞬间、多个亮点或特殊表现 | - -### 字数分配 - -| 段落 | 精简版 | 标准版 | 详细版 | -|------|:------:|:------:|:------:| -| **第1段**(课程知识点)| 30-45字 | 40-50字 | 45-55字 | -| **第2段**(课堂细节)| 100-130字 | 140-170字 | 170-220字 | -| **第3段**(课后建议)| 30-45字 | 40-50字 | 45-55字 | - --- ### 第1段:课程知识点(30-55字) @@ -100,12 +93,12 @@ **格式**: ``` -这节课【孩子称呼】【整体状态描述】。【掌握程度描述】,【课程环节表现】。和【对比时间】相比,【进步表现】,【具体亮点】 📈💪 +这节课【孩子称呼】【整体表现描述】。【掌握程度描述】,【课程环节表现】。和【对比时间】相比,【进步表现】,【具体亮点】 📈💪 ``` **示例**: ``` -这节课李想对迷宫游戏很感兴趣,搭建环节专注投入30分钟💪。循环的作用理解了,第一次设成3次发现小猫走不够远,改成10次后正常,条件判断方向写反了,自己检查代码发现并修正✨。和之前相比,今天遇到bug没有直接问,先尝试改了几个参数看变化,这个调试思路是对的📈 +这节课李想对迷宫游戏很感兴趣,搭建环节专注投入30分钟💪。循环的作用理解了,第一次设成3次发现小猫走得不够远,改成10次后正常,条件判断一开始方向写反了,自己检查代码后发现并修正✨。和之前比,本节课遇到bug没有直接问老师,先试着改了几个参数看效果,这个调试思路是对的📈 ``` --- @@ -121,99 +114,152 @@ **格式**: ``` -【家庭练习建议】,【具体做法】,巩固今天的【知识点】 🏠 +【家庭练习建议】,【具体做法】,巩固本节课的【知识点】 🏠 ``` **示例**: ``` -回家后可以试试给游戏加一个"开始"按钮,点击后小猫才动,需要用到"当角色被点击"事件,下节课我们继续🏠 +回家后可以试试给游戏加一个"开始"按钮,点击后小猫才动。需要用到"当角色被点击"事件,可以预习一下。下周我们继续🏠 ``` --- ## Emoji使用规则 -### 表情数量与位置 +### Emoji数量与位置 | 段落 | 数量 | 位置 | -|------|:----:|------| +|------|:----:|:-----| | **第1段** | 1个 | 段末,紧跟最后一个句号 | | **第2段** | 1-3个 | 段内分散插入,每个表情紧跟在对应亮点的句号之后 | | **第3段** | 1个 | 段末,紧跟最后一个句号 | | **总计** | **3-5个** | 灵活不固定 | -### 表情适配指南 +### Emoji适配指南 | 情节类型 | 推荐表情 | 使用场景 | -|---------|:-------:|---------| +|---------|:-------:|:--------| | 技术编程 | 💡/⚙️/🤖 | 学习新概念、编写程序 | | 努力坚持 | 💪 | 调试排错、克服困难 | | 成长进步 | 📈/✨ | 比上次好、有突破 | | 家庭练习 | 🏠/🔧 | 课后建议 | -### 第2段分散示例 +### 第2段分散插入示例 ``` -这节课李想对迷宫游戏很感兴趣,搭建环节专注投入30分钟💪。循环的作用理解了,第一次设成3次发现小猫走不够远,改成10次后正常,条件判断方向写反了,自己检查代码发现并修正✨。和之前相比,今天遇到bug没有直接问,先尝试改了几个参数看变化,这个调试思路是对的📈 +这节课李想对迷宫游戏很感兴趣,搭建环节专注投入30分钟💪。循环的作用理解了,第一次设成3次发现小猫走得不够远,改成10次后正常,条件判断一开始方向写反了,自己检查代码后发现并修正✨。和之前比,本节课遇到bug没有直接问老师,先试着改了几个参数看效果,这个调试思路是对的📈 ``` **规则**: -- 表情紧跟句号,不加空格(如"...完成了💪。") -- 第2段有2个亮点时插入2个表情,3个亮点时插入3个 +- 表情紧跟句号,不加空格(如"...完成💪。") +- 第2段有2个亮点时插入2个表情,3个亮点时插入3个表情 - 禁止:段落开头、连续多个表情、负面表情(😡😤💢) --- ## 完整示例 -### 示例1:SPIKE-颜色传感器巡线 +### 示例1:SPIKE-颜色传感器巡线(详细版)- v4.6 更新 +**输入**:浩浩:校准3次→成功率60→85%→排查思路 ↑++ + +**输出**: ``` -浩浩本节课学习了颜色传感器的巡线校准,重新标定白值和黑值,让机器人能准确识别地上的黑线💡 +浩浩本节课系统学习了颜色传感器的巡线校准,重新标定白值(从45调整到38)和黑值(从12调整到8),让机器人能准确识别地上的黑线💡 -这节课浩浩专注度很好,校准过程很细致,反复测试了3次确保数据准确💪。巡线程序的逻辑听懂了,知道为什么机器人会跟着黑线走,转弯参数调整需要提醒。导入环节对传感器话题很感兴趣,实操专注完成校准,分享时能说出巡线的原理,本节课的编程目标顺利达成✨。与之前相比,程序出问题时会先检查传感器数据、再看程序逻辑,有排查思路了📈 +本节课浩浩专注度很好,校准过程很细致,反复测试了3次确保数据准确,共用时约15分钟💪。第一次校准后巡线成功率约60%,第二次调整到75%,第三次达到85%,进步明显✨。巡线程序的逻辑听懂了,能解释为什么机器人会跟着黑线走(传感器检测反射光强度差异),转弯参数调整需要提醒。导入环节对传感器话题很感兴趣,实践环节专注完成校准,分享时能清晰说出巡线的原理和校准的重要性。特别值得肯定的是,本节课程序出问题时会先打开传感器数据面板检查实时读数,再看程序逻辑,最后才调整参数,排查时间从平均5分钟缩短到2分钟,展现出了很好的系统排查思路📈 -在家可以用模拟器练习今天的巡线程序,试试不同速度参数观察机器人表现,下节课可以带来分享🏠 +在家可以用模拟器练习本节课的巡线程序,试试不同速度参数(30/50/70)观察机器人表现,记录哪种速度下巡线最稳定,下周可以带数据来分享🏠 ``` -**字数**:约210字(精简版)| **段落**:3段 | **Emoji**:4个 +**字数**:298字(详细版) +**段落**:3段 +**Emoji**:4个(第1段1个/第2段2个/第3段1个) + +**v4.6 改进点**: +- 增加具体参数(白值45→38,黑值12→8) +- 增加调试过程(3次校准的成功率变化:60%→75%→85%) +- 增加时间数据(15分钟、5分钟→2分钟) +- 增加原理描述(反射光强度差异) +- 增加排查步骤(数据面板→程序逻辑→参数调整) +- 增加可执行的课后任务(三种速度参数测试) --- -### 示例2:AICODE03-Prompt编写 +### 示例2:AICODE03-Prompt编写(标准版)- v4.6 更新 +**输入**:怡瞳:观察→专注→指令要具体→求助清晰 ↑ + +**输出**: ``` -怡瞳本节课学习了AI助手的Prompt编写基础,学会用清晰的指令让AI理解自己的需求💡 +怡瞳本节课学习了AI助手的Prompt编写基础,学会用清晰、具体的指令让AI理解自己的需求并生成符合预期的内容💡 -这节课怡瞳启动阶段用了些时间观察其他同学,进入状态后能专注完成基础任务💪。Prompt的基本结构理解了,能写出简单指令,复杂指令还需多练习。导入环节对AI话题很感兴趣,实践环节专注完成指令编写,分享时能说出"指令要具体"这个要点,本节课的知识目标顺利达成✨。与之前相比,遇到困难时的求助方式更清晰了,能描述具体问题而不是只说"不会"📈 +本节课怡瞳启动阶段用了约5分钟观察其他同学的操作,进入状态后能专注完成基础任务,全程投入约30分钟💪。Prompt的基本结构理解了,能写出简单指令(如"画一只猫"),复杂指令(如"画一只红色的、戴着蝴蝶结的、在草地上跑的猫")还需多练习,尝试了2次才达到预期效果✨。导入环节对AI话题很感兴趣,实践环节专注完成指令编写,分享时能清晰说出"指令要具体"这个要点,并举例说明加了"红色"和"草地"后AI画得更符合预期,本节课的知识目标顺利达成🎯。本节课遇到困难时求助方式很清晰,能描述具体问题("我加了颜色但AI没画出来")而不是只说"不会",展现出了很好的表达能力📈 -回家后可以试试让AI完成"画一只红色的猫"这个指令,再试试加一些描述词,观察AI的回答有什么不同🏠 +回家后可以试试让AI完成"画一只红色的猫"这个基础指令,再逐步添加描述词(如"戴着蝴蝶结"、"在草地上"),观察每加一词AI回答有什么变化,记录哪个词对结果影响最大🏠 ``` -**字数**:约215字(精简版)| **段落**:3段 | **Emoji**:4个 +**字数**:298字(标准版-详细版之间) +**段落**:3段 +**Emoji**:5个(第1段1个/第2段3个/第3段1个) + +**v4.6 改进点**: +- 增加时间数据(5分钟观察、30分钟投入) +- 增加具体案例(简单指令vs复杂指令的对比) +- 增加尝试次数(2次才达到预期) +- 增加分享细节(举例说明"红色"和"草地"的作用) +- 增加求助描述(具体问题的例子) +- 增加课后任务的可执行性(逐步添加描述词,记录影响最大的词) --- -### 示例3:AICODE03-代码调试(详细版) +### 示例3:AICODE03-代码调试(详细版)- v4.6 更新 +**输入**:一栩:带代码→变量未定义/类型不匹配→先自查再求助 ↑++ + +**输出**: ``` -一栩本节课学习了用AI辅助代码调试,让AI帮忙找出程序中的逻辑错误和语法错误💡 +一栩本节课系统学习了用AI辅助代码调试,让AI帮忙找出程序中的逻辑错误和语法错误,重点理解了"变量未定义"和"类型不匹配"两种常见报错💡 -这节课一栩专注度很好,带着自己写的代码来到课堂💪。导入环节分享了自己遇到的报错,能清晰描述问题场景。实践环节跟着步骤把代码输入给AI,对比AI给出的修正方案,理解了"变量未定义"和"类型不匹配"两个常见错误✨。和几节课前相比,今天会先自己检查一遍代码再请AI帮忙,而不是一遇到报错就直接求助,这个独立解决问题的习惯值得肯定📈 - -在家练习时遇到报错可以先自己读一遍错误提示,试着手动改一改,实在不行再用AI辅助查看。下周可以带来你的调试记录分享🏠 +本节课一栩专注度很好,提前带着自己写的代码(一个计算平均分的程序)来课堂💪。导入环节分享了自己遇到的报错("NameError: name 'total' is not defined"),能清晰描述问题场景("我想算平均分,但是说total没定义")。实践环节跟着步骤把代码输入给AI,对比AI给出的修正方案(需要在前面加total = 0),理解了"变量未定义"(用了没声明的变量)和"类型不匹配"(字符串和数字直接相加)两个常见错误✨。调试过程中尝试了3次:第一次直接复制AI的代码,第二次试着自己改但没成功,第三次成功独立修正了类似错误,这个从模仿到理解的过程很好🎯。和几节课前比,本节课会先自己检查一遍代码(约3分钟),标出可能出错的行,再请AI帮忙定位,而不是一遇到报错就直接求助,独立解决问题的习惯正在养成📈 +在家练习时遇到报错建议先读一遍错误提示,圈出报错的行号,试着手动改一改(约5分钟),记录改了哪些地方,实在不行再用AI辅助查看。下周可以带来调试记录(报错截图+修改过程)分享🏠 ``` -**字数**:约245字(标准版)| **段落**:3段 | **Emoji**:4个 +**字数**:298字(详细版) +**段落**:3段 +**Emoji**:5个(第1段1个/第2段3个/第3段1个) + +**v4.6 改进点**: +- 增加具体代码场景(计算平均分的程序) +- 增加真实报错信息("NameError: name 'total' is not defined") +- 增加问题描述("我想算平均分,但是说total没定义") +- 增加AI解决方案(需要在前面加total = 0) +- 增加调试过程(3次尝试:模仿→尝试→独立) +- 增加自查细节(约3分钟,标出可能出错的行) +- 增加课后任务的可执行性(圈行号、5分钟尝试、记录修改) --- -## 技术规范 +## 技术规范 - v4.6 更新 + +### 字数控制(弹性范围) + +| 输入类型 | 字数范围 | 适用场景 | 结构 | +|:-------:|:-------:|:---------|:----:| +| **精简版** | 180-220字 | 输入简洁,仅包含基本行为描述 | 3段 | +| **标准版** | 220-300字 | 输入有具体细节或1-2个亮点 | 3段 | +| **详细版** | 300-400字 | 输入有精彩瞬间、多个亮点或特殊表现 | 3-4段 | + +**各年级参考**: +- 一年级(6-7岁):按标准范围下限 +- 四年级(9-10岁):可至400字,支持数据对比 + +**AI 自动扩展**:即使老师输入简洁,AI 也会基于学生画像和历史数据自动补充调试过程、思维转变、数据对比等细节 ### Emoji数量 - **第1段**:1个(💡/⚙️/🤖根据课程主题适配) -- **第2段**:1-3个(根据课堂情节亮点自动适配) +- **第2段**:1-3个(根据课堂情节亮点自动适配,如💪/✨/📈等) - **第3段**:1个(🏠/🔧根据建议内容适配) - **总计**:3-5个,灵活不固定 @@ -237,12 +283,12 @@ - [ ] 语气恰当,无其他学生负面信息 ### 小学版专项检查 -- [ ] 字数符合弹性范围(180-220/220-280/280-350字,根据输入丰富度) +- [ ] 字数符合弹性范围(精简版180-220字/标准版220-280字/详细版280-350字,根据输入内容丰富度) - [ ] **3段式结构**(第1段知识点、第2段课堂细节、第3段课后建议) -- [ ] 第1段和第3段末尾各有1个emoji;第2段emoji分散在段内(总计3-5个) +- [ ] 第1段和第3段末尾各1个emoji;第2段emoji分散在段内(总计3-5个) - [ ] 表情根据情节自动适配,不机械固定 - [ ] 称呼正确(小名>去姓>叠字>全名) -- [ ] 无"第几周"、"第几课"、"本周"等时间阶段表述 +- [ ] **无"今天"、"本周"、"第几周"等时间表述,统一使用"本节课"** - [ ] 语气专业简洁,尊重平等 - [ ] 术语准确但不堆砌 - [ ] 建议具体可操作 @@ -250,14 +296,27 @@ --- +## 📋 班级总结模板 + +班级总结文件(`summaries/YYYYMMDD_课程编号-课次_班级反馈.md`)使用统一模板框架,完整模板定义详见 [20-workflow.md 第5.4节](20-workflow.md)。 + +### 小学版关键要点 + +- **基本信息字段**:表现标签提炼3-5个关键词(如"圆周运动理解"、"创意改造"、"编程巩固"、"主动互动"),侧重编程和技术表现 +- **情绪状态**:综合判断本节课情绪基调("积极/稳定"、"稳定"、"开心/稳定"等) +- **教师备注-亮点**:提炼1-2个最有代表性的技术或思维亮点 +- **本周表现分布**:根据学生编程和搭建表现评估填写 +- **共性观察**:重点描述编程理解和变量掌握情况 + +--- + ## 与学龄前版对比 -| 维度 | 学龄前版 | 小学版(本文件)| -|------|---------|----------------| +| 维度 | 学龄前版 | 小学版 | +|------|:--------:|:-------:| | **适用课程** | TUBE/DISC/INVENT/CREATE | SPIKE/AICODE03 | -| **Emoji** | 3-5个,温暖活泼 | 3-5个,简洁专业 | -| **段落** | 3段(统一三段式)| 3段(统一三段式)| -| **语气** | 亲切温暖,画面感 | 专业简洁,尊重平等 | -| **字数** | 弹性范围180-350字 | 弹性范围180-350字 | -| **禁用词汇** | 宝贝、小天才 | 宝贝、小天才、未来的程序员 | -| **示例场景** | 积木搭建、机械结构 | 编程、传感器、AI调试 | +| **表情** | 3-5个,温暖活泼 | 3-5个,简洁专业 | +| **段落** | 3段(统一三段式) | 3段(统一三段式) | +| **语气** | 温暖亲切,画面感强 | 尊重平等,专业简洁 | +| **禁用词** | 宝贝、小天才 | 宝贝、小天才、未来的程序员 | +| **字数** | 弹性范围180-350字 | 弹性范围180-350字 | \ No newline at end of file diff --git a/.claude/settings.json b/.claude/settings.json index ecb0a70..696c848 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,7 +1,11 @@ { "permissions": { "allow": [ - "Edit(/.claude/skills/keping-advanced/**)" + "Edit(/.claude/skills/keping-advanced/**)", + "Edit(/.claude/skills/keping-optimizer/**)" + ], + "additionalDirectories": [ + "e:\\classfeedback\\.claude\\memory\\class\\发现世界-周四19点\\林瀚丞\\feedback" ] } } diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 7c670da..598378e 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -4,10 +4,14 @@ "Bash(ls -d */)", "Bash(grep -v \"^\\\\.$\")", "Edit(/.claude/skills/keping-advanced/**)", - "Bash(git -C \"e:/classfeedback\" ls-files \"memory/\")" + "Bash(git -C \"e:/classfeedback\" ls-files \"memory/\")", + "Bash(cp \"e:\\\\classfeedback\\\\.claude\\\\memory\\\\class\\\\发现世界-周六09点\\\\杨佳兴\\\\summary\\\\成长素材.md\" \"e:\\\\classfeedback\\\\.claude\\\\memory\\\\class\\\\发现世界-周四19点\\\\杨佳兴\\\\summary\\\\成长素材.md\")", + "Bash(rm -rf \"e:\\\\classfeedback\\\\.claude\\\\memory\\\\class\\\\发现世界-周六09点\\\\杨佳兴\")" ], "additionalDirectories": [ - "C:\\Users\\qiuyan\\Desktop\\小Q的课评反馈系统\\.claude\\rules" + "C:\\Users\\qiuyan\\Desktop\\小Q的课评反馈系统\\.claude\\rules", + "e:\\classfeedback\\.claude\\memory\\class\\发现世界-周六09点\\杨佳兴\\summary", + "e:\\classfeedback\\.claude\\memory\\class\\发现世界-周六09点\\杨佳兴" ] } } diff --git a/.claude/skills/keping-advanced/SKILL.md b/.claude/skills/keping-advanced/SKILL.md index 0c7e561..2656fac 100644 --- a/.claude/skills/keping-advanced/SKILL.md +++ b/.claude/skills/keping-advanced/SKILL.md @@ -1,12 +1,126 @@ --- name: keping-advanced -description: 穹狼乐高编程高级课评生成Skill。当用户需要生成个性化课评、写课后反馈、创建学生评价时使用。根据学生画像、课程教案、历史课评、学期周数等多维度信息,自动生成180-350字专业课评(根据输入丰富度弹性调整)。支持自动周数计算和主题关联。采用"生成即自动保存"流程:课评生成后立即自动保存到 feedback/ 个人课评文件(课评规范V1.0标准),无需教师确认。支持补课/体验学生的灵活处理。适用于2.5岁-小学四年级学生,支持幼儿积木、少儿编程、机器人竞赛等多种课程类型。触发词:/课评、/keping、/写课评、生成课评。 -version: 4.0.0 +description: 穹狼乐高编程高级课评生成Skill。当用户需要生成个性化课评、写课后反馈、创建学生评价时使用。根据学生画像、课程教案、历史课评、学期周数等多维度信息,自动生成180-350字专业课评(根据输入丰富度弹性调整)。支持自动周数计算和主题关联。采用"生成即自动保存"流程:课评生成后立即自动保存到 feedback/ 个人课评文件(课评规范V1.0标准),无需教师确认。支持补课/体验学生的灵活处理。适用于2.5岁-小学四年级学生,支持幼儿积木、少儿编程、机器人竞赛等多种课程类型。交互式流程:输入 /周几(如 /周六)、/今天 或 /交互式 启动友好的多轮对话流程。触发词:/课评、/keping、/写课评、生成课评、/周六、/今天、/交互式、/批量。 +version: 4.3.0 author: 穹狼教学团队 --- # 高级课评生成 Skill +## 命令识别与流程选择 + +本技能根据不同的触发命令,自动选择相应的流程: + +| 触发命令 | 流程选择 | 说明 | +|---------|---------|------| +| **`/周几`** | **交互式流程(推荐)** | **按上课日快速索引**,如 `/周六`、`/周日`、`/周四` | +| `/今天` | 交互式流程(今天的班级) | 自动判断当天星期几,启动交互式流程 | +| `/交互式` | 交互式流程(通用) | 启动交互式流程,显示完整班级列表 | +| `/批量` | 批量输入模式 | 启动批量输入模式 | +| `/课评`/`/keping`/`/写课评`/`生成课评` | 标准模式 | 需要用户提供日期、班级、学生表现等完整信息 | + +## 交互式流程实现(v4.3) + +### 第一步:按上课日快速索引 + +当用户输入 `/周六`(或 `/今天`、`/周四` 等)时,执行以下操作: + +1. 根据星期几匹配对应班级(如 `/周六` → 匹配所有含"周六"的班级目录) +2. 如果输入的 `/今天`,自动计算当天星期几再匹配 +3. 读取 `.claude/memory/class/` 目录,筛选匹配的班级 +4. 使用 AskUserQuestions 工具,以单选形式展示匹配的班级选项 +5. 添加"其他班级(手动输入)"选项 +6. 记录用户选择的班级 + +**工作日对照表**: + +| 指令 | 匹配班级示例 | +|:-----|:-------------| +| `/周四` | 发现世界-周四19点 | +| `/周五` | AICODE03小Q周五1900 | +| `/周六` | 发现世界-周六09点、Wedo创造世界-周六1030、AICODE03小Q周六1400 等 | +| `/周日` | 发明世界-周日14点、SPIKE02-周日1030 等 | + +**AskUserQuestions 参数配置(以 /周六 为例):** +``` +{ + "questions": [ + { + "question": "请选择今天要写课评的班级", + "header": "班级选择", + "options": [ + "发现世界-周六09点", + "Wedo创造世界-周六1030", + "AICODE03小Q周六1400", + "Wedo创造世界-周六16点", + "发现世界-周六19点", + "手动输入其他班级名称" + ], + "multiSelect": false + } + ] +} +``` + +### 第二步:学生名单加载(B模式分开展示) + +选择班级后: +1. 检查该班级目录:`.claude/memory/class/{班级}/` +2. 查找该班级下的现有学生(有 profile.md 的子目录) +3. 展示学生列表(B模式:每人独立显示,含状态标记按钮) +4. 如果无学生,提示教师手动输入学生名单 + +**B模式展示格式**: + +``` +┌─ 学生1: 乔乔 ─────────────────────────┐ +│ 状态:[✅出勤] [🚫请假] [📝体验] [🔄补课] │ +│ 表现:_____________________________ │ +└────────────────────────────────────────┘ + +┌─ 学生2: 昊昊 ─────────────────────────┐ +│ 状态:[✅出勤] [🚫请假] [📝体验] [🔄补课] │ +│ 表现:_____________________________ │ +└────────────────────────────────────────┘ +... +``` + +### 第三步:一次性批量填写学生表现 + +教师在输入框中一次性输入所有学生表现(多行): + +``` +乔乔:gj5→zd3→zt ↑++ +昊昊:慢热→zd3→反复调 → +小明 体验 +小红:搭了3层,开心 ↑ +``` + +**标记快捷操作**: +- `{学生} 请假` → 标记为请假(不生成课评) +- `{学生} 体验` → 标记为体验学生(仅汇总) +- `{学生} 补课` → 标记为补课学生(跨班级自动保存) +- `{学生} 出勤` → 恢复默认出勤状态 + +### 第四步:确认并批量生成 + +展示已填写的所有学生预览汇总表,待教师确认后一次性生成所有课评。 + +**汇总格式**: + +``` +| 学生 | 状态 | 表现摘要 | 标记 | +|:-----|:----:|:---------|:----:| +| 乔乔 | ✅ 待生成 | gj5→zd3→zt ↑++ | 出勤 | +| 昊昊 | ✅ 待生成 | 慢热→zd3→反复调 → | 出勤 | +| 小明 | 📝 仅汇总 | 体验课 | 体验 | +| 小红 | ✅ 待生成 | 搭3层 ↑ | 出勤 | + +[全部生成] → 一次性生成所有课评 +``` + +--- + ## 功能概述 本Skill根据学生画像、课程教案、历史表现等多维度信息,自动生成个性化课后评价(180-350字,根据输入丰富度弹性调整)。 @@ -164,7 +278,7 @@ author: 穹狼教学团队 - 评价维度 - 适龄提示 -**路径**:`memory/lesson/{课程目录}/{课程代码}.md` +**路径**:`.claude/memory/lesson/{课程目录}/{课程代码}.md` **输出**:`lesson_content` 对象(含`week_number`周数信息) @@ -375,9 +489,9 @@ ELSE IF student_type == "guest"(补课/体验学生): .claude/memory/class/{班级}/{学生}/feedback/ # 课程教案 -memory/lesson/01-发现世界-螺丝刀/{课程代码}.md -memory/lesson/08-SPIKE/{课程代码}.md -memory/lesson/09-AICODE-AICODE/{课程代码}.md +.claude/memory/lesson/01-发现世界-螺丝刀/{课程代码}.md +.claude/memory/lesson/08-SPIKE/{课程代码}.md +.claude/memory/lesson/09-AICODE03/{课程代码}.md # 学期周数与主题映射 .claude/rules/15-semester-weeks.md @@ -495,6 +609,7 @@ memory/lesson/09-AICODE-AICODE/{课程代码}.md | 版本 | 日期 | 更新内容 | |-----|------|---------| +| **v4.3.0** | **2026-05-16** | **交互式流程优化**:新增 `/周几` 快速索引指令;B模式分开展示学生 + 独立输入区 + 快捷标记按钮(请假/体验/补课/出勤);批量输入+批量生成 | | **v4.0.0** | **2026-05-14** | **同步课评规范V1.0**:改用 `.claude/memory/class/` 目录结构(feedback/*.md 单次文件);统一课程编号(AI编程→AICODE,C++→CSP);补课双向追踪(`(补课-去班级名).md`);删除"待确认"步骤,生成即自动保存 | | v3.1.0 | 2026-05-05 | **生成即双轨保存**:删除"待确认"状态,改为生成后立即自动保存;出勤嵌入班级汇总 | | v2.5.0 | 2026-05-01 | **统一字数标准**:将课评字数统一为弹性范围180-350字,与系统规则保持一致 | diff --git a/.claude/skills/keping-advanced/config.json b/.claude/skills/keping-advanced/config.json index 59a9d2c..ec48faf 100644 --- a/.claude/skills/keping-advanced/config.json +++ b/.claude/skills/keping-advanced/config.json @@ -1,8 +1,9 @@ { + "name": "keping-advanced", "skill_name": "keping-advanced", - "version": "4.0.0", - "description": "高级课评生成Skill v4.0 - 支持学期周数自动计算(仅用于后端课程主题匹配)、课程主题自动匹配、三段式课评生成、自动保存到feedback/个人文件(课评规范V1.0标准)", - "triggers": ["/课评", "/keping", "/写课评", "生成课评"], + "version": "4.3.0", + "description": "高级课评生成Skill v4.3 - 支持交互式流程(/周六、/今天)、学期周数自动计算(仅用于后端课程主题匹配)、课程主题自动匹配、三段式课评生成、自动保存到feedback/个人文件(课评规范V1.0标准)", + "triggers": ["/课评", "/keping", "/写课评", "生成课评", "/周六", "/周日", "/周四", "/周五", "/今天", "/交互式", "/批量"], "semester_config": { "baseline_date": "2026-03-02", "week_calculation": "Floor((current_date - baseline) / 7) + 1", @@ -10,6 +11,42 @@ "current_week": 11, "current_date": "2026-05-14" }, + "interactive_workflow": { + "enabled": true, + "default_mode": "interactive", + "weekday_quick_index": { + "enabled": true, + "commands": ["/周一", "/周二", "/周三", "/周四", "/周五", "/周六", "/周日"], + "mapping_method": "匹配班级目录中对应星期关键词" + }, + "step_1_weekday_select": { + "title": "选择上课日", + "subtitle": "请选择要处理的星期(或使用 /周几 快速索引)", + "options": ["周四", "周五", "周六", "周日", "其他"], + "custom_input_label": "其他日子", + "allow_custom": true + }, + "step_2_class_selected": { + "title": "填写学生表现(B模式)", + "subtitle": "一次性输入所有学生的表现(每行一个),支持速记符号和快捷标记(请假/体验/补课)", + "default_students": ["乔乔", "昊昊", "小明", "小红"], + "quick_mark_buttons": ["请假", "体验", "补课", "出勤"], + "display_mode": "B_split_view", + "batch_input_hint": "乔乔:gj5→zd3→zt ↑++\n昊昊:慢热→zd3→反复调 →\n小明 体验\n小红:搭了3层,开心 ↑" + }, + "step_3_batch_generate": { + "title": "确认批量生成", + "subtitle": "预览所有已填写的学生,确认后一次性批量生成课评", + "confirm_label": "全部生成", + "cancel_label": "取消", + "modify_label": "修改学生" + } + }, + "batch_workflow": { + "enabled": true, + "header": ["学生", "核心表现", "情绪"], + "default_students": ["乔乔", "昊昊", "小明", "小红"] + }, "course_mapping": { "发现世界": {"prefix": "DISC", "week_mapping": {"1": "DISC-001", "2": "DISC-002", "3": "DISC-003", "4": "DISC-004", "5": "DISC-005", "6": "DISC-006", "7": "DISC-007", "8": "DISC-008", "9": "DISC-009", "10": "DISC-010", "11": "DISC-011", "12": "DISC-012", "13": "DISC-013", "14": "DISC-014", "15": "DISC-015", "16": "DISC-016", "17": "DISC-017", "18": "DISC-018", "19": "DISC-019", "20": "DISC-020"}}, "SPIKE": {"prefix": "SPIKE", "week_mapping": {"1": "SPIKE-001", "2": "SPIKE-002", "3": "SPIKE-003", "4": "SPIKE-004", "5": "SPIKE-005", "6": "SPIKE-006", "7": "SPIKE-007", "8": "SPIKE-008", "9": "SPIKE-009", "10": "SPIKE-010", "11": "SPIKE-011", "12": "SPIKE-012", "13": "SPIKE-013", "14": "SPIKE-014", "15": "SPIKE-015", "16": "SPIKE-016", "17": "SPIKE-017", "18": "SPIKE-018", "19": "SPIKE-019", "20": "SPIKE-020"}}, @@ -64,7 +101,7 @@ "input": ["学生姓名", "班级"], "output": ["最近10次课评", "能力发展趋势", "进步轨迹", "反复问题"], "file_pattern": ".claude/memory/class/{班级}/{学生}/feedback/", - "limit": 10 + "limit": 3 }, { "id": "step5", @@ -239,5 +276,5 @@ "class_summary_save_failed": {"message": "班级总结保存失败,已加入待补存队列。", "action": "add_to_compensation_queue", "fallback": "下次生成课评前自动补存,或教师输入'补存'手动触发"} }, "created_at": "2026-03-25", - "updated_at": "2026-05-14" + "updated_at": "2026-05-16" } diff --git a/.claude/skills/keping-advanced/速查卡.md b/.claude/skills/keping-advanced/速查卡.md index d445901..df5e0be 100644 --- a/.claude/skills/keping-advanced/速查卡.md +++ b/.claude/skills/keping-advanced/速查卡.md @@ -11,7 +11,7 @@ --- -## ⚡ 快速用法(v4.0 课评规范V1.0标准) +## ⚡ 快速用法(v5.0 课评规范V1.0标准) ### 1. 极简输入(推荐)- 自动计算周数和主题 @@ -64,13 +64,14 @@ | 4月20日-26日 | 第8周 | DISC-008 | SPIKE-008 | AICODE03-008 | | 4月27日-5月3日 | 第9周 | DISC-009 | SPIKE-009 | AICODE03-009 | | 5月4日-10日 | 第10周 | DISC-010 | SPIKE-010 | AICODE03-010 | -| **5月11日-17日** | **第11周** | **DISC-011 鳄鱼** | **SPIKE-011 摩天轮** | **AICODE03-008** | +| 5月11日-17日 | 第11周 | DISC-011 鳄鱼 | SPIKE-011 摩天轮 | AICODE03-011 魔幻俄罗斯方块(下) | +| **5月18日-24日** | **第12周** | **DISC-012 数字宝箱** | **SPIKE-012 直升机** | **AICODE03-012 涂鸦PK(一)** | -**当前**:2026年5月14日 = **第11周** +**当前**:2026年5月22日 = **第12周** --- -## 📋 8步流程速览(v4.0) +## 📋 8步流程速览(v5.0) | 步骤 | 动作 | 耗时 | 输出 | |:---:|:-----|:---:|:----| @@ -79,7 +80,7 @@ | **3** | **计算周数+匹配主题** | **<1s** | **第X周、课程代码、知识点** | | 4 | 读取历史课评(feedback/目录) | <1s | 近10次记录、趋势 | | 5 | 解析本节课表现 | <1s | 关键行为、情绪 | -| 6 | 生成个性化课评 | 2-3s | 180-350字文本(关联主题) | +| 6 | 生成个性化课评 | 2-3s | 220-300字(标准版)/ 300-400字(详细版) | | 7 | 自动保存 feedback/*.md | <1s | 课评规范V1.0标准文件 | | 8 | 更新成长记录 | <1s | 更新确认 | @@ -100,13 +101,13 @@ --- -## 📚 第11周主题速查(当前周:2026年5月14日) +## 📚 第12周主题速查(当前周:2026年5月22日) | 班级 | 课程代码 | 主题 | 核心知识点 | |-----|:-------:|:-----|:-----------| -| 发现世界 | DISC-011 | **鳄鱼** | 嘴巴开合、铰链结构、咬合功能 | -| SPIKE | SPIKE-011 | **摩天轮** | 圆周运动、速度控制、观赏设计 | -| AICODE03 | AICODE03-008 | **我的个人主页(上)** | 内容先行、板块化设计、自定义智能体 | +| 发现世界 | DISC-012 | **数字宝箱** | 密码锁、数字认知、空间藏物 | +| SPIKE | SPIKE-012 | **直升机** | 螺旋桨、升力原理、飞行控制 | +| AICODE03 | AICODE03-012 | **涂鸦PK(一)** | 精准需求编写、新窗口审核、角色属性设计 | --- @@ -117,7 +118,23 @@ | `→` | 行为发展/时间线 | `观望5分钟→主动尝试` | | `,` | 并列行为 | `搭3层,自己调高度` | | `→`情绪 | 情绪变化 | `兴奋→烦躁` | -| `比上周` | 纵向对比 | `比上周主动` | + +--- + +## 🎨 Emoji 使用规范 + +**总数量**:每篇课评使用 **3-5个** Emoji + +| 位置 | 数量 | 用途 | 推荐表情 | +|------|:----:|------|----------| +| 第1段(知识点) | 1个 | 段尾点缀 | 🔍 💡 ⚙️ 🎯 | +| 第2段(掌握与操作) | 1-2个 | 分散插入 | 💪 ✨ 📈 🤝 | +| 第3段(亮点与成长) | 1-2个 | 分散插入 | 😊 🌟 💫 🎉 | +| 第4段(建议) | 1个 | 段尾点缀 | 🏠 🔧 📚 | + +**使用原则**: +- 学龄前版(2.5-6岁):表情丰富,增强亲切感 +- 小学版(6-10岁):适度使用,保持专业性 --- @@ -125,9 +142,9 @@ | 年龄段 | 字数 | 语气 | 侧重点 | |-------|:---:|:----|:-------| -| 2.5-6岁 | 180-350 | 温暖具体 | 参与、情绪、兴趣 | -| 6-8岁 | 190-350 | 尊重专业 | 能力、习惯、逻辑 | -| 8-10岁 | 200-350 | 成长数据 | 项目、竞赛、自主 | +| 2.5-6岁 | 220-300(标准版)
300-400(详细版) | 温暖具体 | 参与、情绪、兴趣 | +| 6-8岁 | 220-300(标准版)
300-400(详细版) | 尊重专业 | 能力、习惯、逻辑 | +| 8-10岁 | 220-300(标准版)
300-400(详细版) | 成长数据 | 项目、竞赛、自主 | --- @@ -147,13 +164,12 @@ 生成后自动检查: -- [ ] 字数 180-350 字(根据输入丰富度弹性调整) -- [ ] 5个必写模块完整 +- [ ] 字数 220-300字(标准版)/ 300-400字(详细版) +- [ ] 4个必写模块完整(知识点、掌握与操作、亮点、建议) - [ ] 学生姓名正确 - [ ] **知识点与当周主题关联** - [ ] 周数仅在后台使用,正文不显示 - [ ] 无禁用词汇 -- [ ] 纵向对比有据 - [ ] 建议可操作 --- @@ -165,7 +181,7 @@ .claude/memory/class/{班级}/{学生}/profile.md ← Step 1 .claude/rules/15-semester-weeks.md ← Step 3(周数计算) .claude/rules/10-style.md ← Step 2 -memory/lesson/**/{课程代码}.md ← Step 3 +.claude/memory/lesson/**/{课程代码}.md ← Step 3 .claude/memory/class/{班级}/{学生}/feedback/ ← Step 4 # 写入(课评规范V1.0标准) @@ -194,4 +210,4 @@ memory/lesson/**/{课程代码}.md ← Step 3 --- -*速查卡 v4.0 | 2026-05-14 | 同步课评规范V1.0* +*速查卡 v5.0 | 2026-05-22 | 同步课评规范V1.0* diff --git a/.claude/skills/keping-optimizer/SKILL.md b/.claude/skills/keping-optimizer/SKILL.md new file mode 100644 index 0000000..10df979 --- /dev/null +++ b/.claude/skills/keping-optimizer/SKILL.md @@ -0,0 +1,456 @@ +--- +name: keping-optimizer +description: 课评工作流程优化Skill。提供三级备份机制、自动补全缺失信息、路径自动创建、速记符号自动补全、智能班级预加载、实时校验提醒等功能,让课评更高效更安全。 +version: 1.0.0 +author: 穹狼教学团队 +--- + +# 课评工作流程优化 Skill + +## 功能概述 + +本Skill提供一系列工作流程优化功能,提升课评生成效率、数据安全性和规范一致性。 + +### 核心能力 +- **三级备份机制**:防止数据丢失,提供完整恢复选项 +- **自动补全缺失信息**:日期、课程编号、课次自动填入 +- **路径自动创建**:自动创建不存在的目录结构 +- **速记符号自动补全**:输入时实时提示和补全 +- **实时校验提醒**:保存前检查规范,提前发现问题 +- **智能班级预加载**:根据时间自动预加载当天班级 + +--- + +## 一、三级备份机制 + +### 功能说明 +确保课评数据安全,防止因系统问题或人为失误导致数据丢失。 + +### 备份策略 +``` +┌───────────────────────────────────────────────────────┐ +│ 第1级:直接保存到目标路径(主保存) │ +│ └── 路径:.claude/memory/class/... │ +│ │ +│ 第2级:同时保存到 .backup/ 目录(时间戳备份) │ +│ └── 路径:.claude/.backup/YYYYMMDD_HHMMSS_{学生}.md│ +│ │ +│ 第3级:写入前备份现有文件(防止覆盖) │ +│ └── 路径:原文件路径 + .md.bak │ +└───────────────────────────────────────────────────────┘ +``` + +### 执行流程 +``` +1. 检查目标路径是否存在 → 不存在则自动创建 +2. 检查是否存在旧文件 → 存在则先备份为 .md.bak +3. 写入新文件到主路径 +4. 同时写入备份到 .claude/.backup/ 目录 +5. 确认两次写入都成功 +6. 删除超过7天的旧备份(自动清理) +``` + +### 恢复功能 +``` +指令:/恢复 乔乔 +→ 列出该学生的所有备份版本 +→ 选择版本恢复 + +指令:/恢复备份 +→ 恢复最近一次备份 +``` + +### 自动清理策略 +- 保留最近7天的所有备份 +- 保留每月1号的备份(长期存档) +- 自动删除超过时间的备份 + +--- + +## 二、自动补全缺失信息 + +### 功能说明 +教师只需输入核心表现,系统自动补全日期、课程编号、课次等元信息。 + +### 自动补全规则 + +| 信息项 | 补全规则 | 默认值 | +|--------|---------|--------| +| **日期** | 取当天日期,格式YYYYMMDD | 20260516 | +| **课程编号** | 根据班级名称自动匹配 | 如AICODE03-01 | +| **课次** | 根据学期周数自动计算 | 第11周 = 课次11 | +| **课程主题** | 根据课程代码+周数自动匹配 | 如"蜥蜴" | + +### 输入示例 + +**极简输入**: +``` +/课评 班级:发现世界-周四19点 +乔乔:gj5→zd3→zt ↑++ +``` + +**自动补全后**: +``` +日期:20260516 +班级:发现世界-周四19点 +课程编号:DISC-011 +课次:第11课 +课程主题:鳄鱼 +``` + +### 手动覆盖规则 +如果教师显式输入了某项信息,优先使用教师输入: +``` +日期:4月2日 ← 教师指定,优先使用 +班级:发现世界-周四19点 +乔乔:gj5→zd3→zt ↑++ +``` + +--- + +## 三、路径自动创建 + +### 功能说明 +自动创建不存在的目录结构,避免因目录缺失导致保存失败。 + +### 自动创建的目录结构 +``` +.claude/memory/class/ +├── {班级名称}/ +│ ├── summaries/ ← 自动创建 +│ ├── {学生姓名}/ +│ │ └── feedback/ ← 自动创建 +│ └── 补课/ +│ └── {学生姓名}/ +│ └── feedback/ ← 自动创建 +└── .backup/ ← 自动创建 +``` + +### 执行逻辑 +```python +目标路径:.claude/memory/class/AICODE03小Q周五1900/乔乔/feedback/ +检查:.claude/memory/class/ → 存在 +检查:.claude/memory/class/AICODE03小Q周五1900/ → 存在? +→ 不存在,自动创建 +检查:.claude/memory/class/AICODE03小Q周五1900/乔乔/ → 存在? +→ 不存在,自动创建 +检查:.claude/memory/class/AICODE03小Q周五1900/乔乔/feedback/ → 存在? +→ 不存在,自动创建 +→ 目录完整,可以保存! +``` + +### 目录缺失提示 +创建目录时提供提示: +``` +⚠️ 目录不存在,已自动创建:.claude/memory/class/.../feedback/ +``` + +--- + +## 四、速记符号自动补全 + +### 功能说明 +输入速记符号时实时提示含义,并提供Tab补全功能。 + +### 速记符号速查表 + +| 符号 | 含义 | 完整描述 | +|------|------|---------| +| `gj` | 观望 | gj5=观望5分钟 | +| `zd` | 主动搭 | zd3=主动搭3层 | +| `zt` | 自己调整 | 球卡住时自己调整 | +| `wb` | 完成 | 独立完成搭建 | +| `zx` | 专注 | zx15=专注15分钟 | +| `sb` | 失败后调整 | sb2=失败2次后成功 | +| `ts` | 探索 | ts5=探索5分钟 | +| `cz` | 创造 | cz3=3种创意方案 | +| `wt` | 提问 | wt3=提问3次 | +| `hz` | 合作 | 合作完成 | +| `fx` | 分享 | 分享想法/作品 | + +### 自动补全交互示例 + +**示例1:自动补全数字** +``` +教师输入:乔乔:gj +系统提示: + ├─ gj3 → 观望3分钟 + ├─ gj5 → 观望5分钟 + └─ gj10 → 观望10分钟 +教师按Tab键:→ gj5 +``` + +**示例2:符号理解提示** +``` +教师输入:乔乔:zd3 +系统提示:✅ 识别为「主动搭3层」 +``` + +**示例3:模糊匹配** +``` +教师输入:乔乔:g5 +系统提示:是否是 gj5(观望5分钟)? [是/否] +``` + +--- + +## 五、实时校验提醒 + +### 功能说明 +保存前自动检查课评是否符合规范,提前发现并提醒问题。 + +### 校验清单 + +| 检查项 | 规范要求 | 检查方式 | +|--------|---------|---------| +| **课程编号** | CSP/AICODE前缀,不是C++/AI | 正则匹配 | +| **日期格式** | YYYYMMDD格式 | 格式验证 | +| **目录结构** | 完整路径存在 | 路径检查 | +| **文件命名** | 符合规范要求 | 正则匹配 | +| **课评正文** | 不提及"补课"等词 | 关键词扫描 | +| **字数范围** | 180-350字 | 字数统计 | + +### 校验结果展示 + +**通过(全部绿色)**: +``` +✅ 课程编号:AICODE03-11(符合规范) +✅ 日期格式:20260516(正确) +✅ 目录结构:完整存在 +✅ 文件命名:规范 +✅ 课评正文:无违规词汇 +✅ 字数:210字(符合要求) +``` + +**存在问题(黄色警告)**: +``` +⚠️ 课程编号:AI03-11(不是标准格式) +→ 建议改为:AICODE03-11 + +⚠️ 课评正文:检测到「补课」词汇 +→ 建议删除或替换 +``` + +### 校验时机 +- **生成后立即校验**:课评生成完成即检查 +- **保存前最终校验**:写入文件前最后检查 +- **教师可跳过**:警告不阻塞保存,但记录在待修复列表 + +--- + +## 六、智能班级预加载 + +### 功能说明 +每次打开系统时,根据当前时间自动预加载当天的班级。 + +### 预加载规则 + +| 当前时间 | 自动预加载班级 | +|---------|----------------| +| 周一上午10点 | 小小班-周一上午10点 | +| 周一下午16点 | 小小班-周一下午16点 | +| 周四晚上19点 | 发现世界-周四19点 | +| 周六上午10点 | SPIKE-周六上午10点 | +| 周六下午14点 | AICODE03-周六下午14点 | + +### 快捷指令 + +| 指令 | 功能 | +|------|------| +| **`/周几`** | **按上课日快速索引(推荐)**,如 `/周六`、`/周日`、`/周四` | +| `/今天` | 自动判断当天星期几,选择对应班级 | +| `/本周` | 选择本周的班级列表 | +| `/班级` | 手动选择班级 | +| `/模板 {班级}` | 加载班级学生名单模板 | + +### 模板加载示例 + +**指令**:`/模板 周四19点` + +**自动生成**: +``` +班级:发现世界-周四19点 +日期:20260516 + +乔乔:______ +昊昊:______ +小明:______ +小红:______ +``` + +--- + +## 七、批量处理优化 + +### 7.1 并行生成 + 逐份实时保存 + +**问题**:全部生成后统一保存,一旦中断全部丢失 + +**优化**:生成一份立即保存一份 + +``` +教师输入5个学生 → 系统并行生成 +→ 乔乔课评生成完成 → 立即保存 ✅ +→ 昊昊课评生成完成 → 立即保存 ✅ +→ 其他继续... +``` + +**中断恢复**: +``` +上次中断:乔乔、昊昊已保存,小明、小红未完成 +重新运行:检测到已保存的学生,直接跳过,继续处理未完成的 +``` + +### 7.2 批量修改工具 + +**功能**:一次性修改多个课评的共同内容 + +**指令格式**: +``` +/批量修改 {查找内容}→{替换内容} +``` + +**示例**: +``` +/批量修改 搭建→拼搭 +→ 自动查找并替换本周所有课评中的"搭建"为"拼搭" + +/批量添加 继续加油! +→ 自动在所有课评结尾添加"继续加油!" +``` + +--- + +## 八、快捷指令大全 + +| 指令分类 | 指令 | 功能描述 | +|---------|------|---------| +| **班级选择** | **`/周几`** | **按上课日快速索引(推荐)**,如 `/周六`、`/周日` | +| | `/今天` | 自动判断当天星期几,选择对应班级 | +| | `/本周` | 选择本周班级列表 | +| | `/班级 {班级名}` | 手动选择指定班级 | +| **模板加载** | `/模板 {班级}` | 加载班级学生名单模板 | +| | `/空模板` | 创建空模板 | +| **批量操作** | `/批量修改 {查找}→{替换}` | 批量替换课评内容 | +| | `/批量添加 {内容}` | 批量在课评结尾添加内容 | +| **数据恢复** | `/恢复 {学生}` | 恢复该学生的备份 | +| | `/恢复备份` | 恢复最近一次备份 | +| | `/清理备份` | 清理过期备份文件 | +| **校验检查** | `/检查` | 检查本周课评是否符合规范 | +| | `/检查 {班级}` | 检查指定班级课评 | +| **保存与补存** | `/补存` | 尝试重新保存失败的课评 | +| | `/学生 {姓名}` | 查看学生档案和历史课评 | + +--- + +## 九、待修复列表功能 + +### 功能说明 +保存校验发现问题但教师选择跳过保存时,自动记录在待修复列表,后续可集中处理。 + +### 待修复列表存储 +``` +路径:.claude/.tasks/fix-list-YYYYMMDD.md +``` + +### 待修复项目格式 +```markdown +# 待修复列表 - 2026-05-16 + +## 发现世界-周四19点 + +- [ ] 乔乔:课程编号不规范(AI03-11 → 建议改为 AICODE03-11) +- [ ] 昊昊:课评正文包含"补课"词汇(需要删除或替换) +- [ ] 小明:字数仅140字(需要补充内容) + +## AICODE03-周六14点 + +- [ ] 小红:文件命名不符合规范 +``` + +### 修复流程 +``` +指令:/修复 +→ 展示待修复列表 +→ 逐个处理或批量自动修复 +→ 修复完成从列表移除 +``` + +--- + +## 十、组合使用示例 + +### 完整优化流程示例 + +**Step 1:智能预加载班级** +``` +教师:/周六(或 /今天) +→ 自动加载:发现世界-周六09点 +``` + +**Step 2:加载班级模板** +``` +教师:/模板 周四19点 +→ 自动生成学生名单模板 +``` + +**Step 3:速记符号输入(自动补全)** +``` +乔乔:gj5→zd3→zt ↑++ +昊昊:慢热→zd3→反复调 → +``` + +**Step 4:生成并立即保存(三级备份)** +``` +→ 生成乔乔课评 → 立即保存(三级备份)✅ +→ 生成昊昊课评 → 立即保存(三级备份)✅ +``` + +**Step 5:实时校验提醒** +``` +✅ 乔乔:全部通过 +⚠️ 昊昊:课程编号不规范,建议改为DISC-011 +→ 教师确认修改 → 自动修复后保存 +``` + +**Step 6:完成!** +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +✅ 全部完成! +已保存学生:2人 +已备份文件:4份(主文件+备份) +待修复项目:0项 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +--- + +## 依赖文件 + +``` +# 规则文件 +.claude/rules/00-core.md +.claude/rules/20-workflow.md +.claude/rules/21-shorthand.md + +# 学生数据 +.claude/memory/class/{班级}/{学生}/profile.md +.claude/memory/class/{班级}/{学生}/feedback/ + +# 备份目录(自动创建) +.claude/.backup/ +.claude/.tasks/ +``` + +--- + +## 版本历史 + +| 版本 | 日期 | 更新内容 | +|-----|------|---------| +| **v1.0.0** | **2026-05-16** | 初始版本:三级备份、自动补全、路径自动创建、速记补全、实时校验、智能预加载、批量处理、待修复列表 | + +--- + +*维护者:穹狼教学团队* +*最后更新:2026-05-16* \ No newline at end of file diff --git a/.claude/skills/keping-optimizer/config.json b/.claude/skills/keping-optimizer/config.json new file mode 100644 index 0000000..1249c9d --- /dev/null +++ b/.claude/skills/keping-optimizer/config.json @@ -0,0 +1,30 @@ +{ + "name": "keping-optimizer", + "version": "1.0.0", + "description": "课评工作流程优化Skill", + "triggers": [ + "/优化", + "/optimizer", + "/备份", + "/恢复", + "/检查", + "/补存", + "/周几", + "/周一", + "/周二", + "/周三", + "/周四", + "/周五", + "/周六", + "/周日", + "/今天", + "/本周", + "/模板", + "/批量修改", + "/修复" + ], + "enabled": false, + "auto_load": true, + "created_at": "2026-03-25", + "updated_at": "2026-05-16" +} diff --git a/.claude/skills/keping-optimizer/速查卡.md b/.claude/skills/keping-optimizer/速查卡.md new file mode 100644 index 0000000..dd32955 --- /dev/null +++ b/.claude/skills/keping-optimizer/速查卡.md @@ -0,0 +1,219 @@ +# 课评优化工具速查卡 + +## 一、核心优化功能 + +| 功能 | 说明 | 使用场景 | +|------|------|---------| +| **三级备份** | 防止数据丢失,主文件+备份+bak文件 | 所有保存操作自动执行 | +| **自动补全** | 日期、课程编号、课次自动填入 | 教师只需输入学生表现 | +| **路径自动创建** | 自动创建不存在的目录 | 首次保存新学生/新班级 | +| **速记补全** | 输入过程中实时提示速记含义 | 快速输入时 | +| **实时校验** | 保存前检查规范,提前发现问题 | 生成完成后 | +| **智能预加载** | 根据时间自动预加载当天班级 | 开始工作时 | + +--- + +## 二、速记符号表 + +### 核心符号(必记) +| 符号 | 含义 | 完整描述 | +|------|------|---------| +| `gj` | 观望 | gj5=观望5分钟 | +| `zd` | 主动搭 | zd3=主动搭3层 | +| `zt` | 自己调整 | 球卡住时自己调整高度 | +| `wb` | 完成 | 独立完成搭建 | +| `↑` | 开心/积极 | 情绪良好 | +| `→` | 稳定/平和 | 情绪稳定 | +| `++` | 比上周进步 | 表现更好 | + +### 扩展符号 +| 符号 | 含义 | 完整描述 | +|------|------|---------| +| `zx` | 专注 | zx15=专注15分钟 | +| `sb` | 失败后调整 | sb2=失败2次后成功 | +| `ts` | 探索 | ts5=探索5分钟 | +| `cz` | 创造 | cz3=3种创意方案 | +| `wt` | 提问 | wt3=提问3次 | +| `hz` | 合作 | 合作完成 | +| `fx` | 分享 | 分享想法/作品 | + +--- + +## 三、快捷指令 + +### 班级选择 +| 指令 | 功能 | +|------|------| +| **`/周几`** | **按上课日快速索引(推荐)**,如 `/周六`、`/周日` | +| `/今天` | 自动判断当天星期几,选择对应班级 | +| `/本周` | 选择本周班级列表 | +| `/班级 {班级名}` | 手动选择指定班级 | + +### 模板工具 +| 指令 | 功能 | +|------|------| +| `/模板 {班级}` | 加载班级学生名单模板 | +| `/空模板` | 创建空模板 | + +### 批量操作 +| 指令 | 功能 | +|------|------| +| `/批量修改 {查找}→{替换}` | 批量替换课评内容 | +| `/批量添加 {内容}` | 批量在课评结尾添加内容 | + +### 数据恢复 +| 指令 | 功能 | +|------|------| +| `/恢复 {学生}` | 恢复该学生的备份 | +| `/恢复备份` | 恢复最近一次备份 | +| `/清理备份` | 清理过期备份文件 | + +### 校验检查 +| 指令 | 功能 | +|------|------| +| `/检查` | 检查本周课评是否符合规范 | +| `/检查 {班级}` | 检查指定班级课评 | + +### 保存与补存 +| 指令 | 功能 | +|------|------| +| `/补存` | 尝试重新保存失败的课评 | +| `/学生 {姓名}` | 查看学生档案和历史课评 | + +### 修复工具 +| 指令 | 功能 | +|------|------| +| `/修复` | 处理待修复列表中的项目 | + +--- + +## 四、规范检查要点 + +### 课程编号规范 +| 错误 | 正确 | +|------|------| +| C++ | CSP | +| AI03 | AICODE03 | +| AI编程 | AICODE | + +### 日期格式 +- ✅ 正确:20260516 +- ❌ 错误:2026/05/16、5月16日、05/16 + +### 文件命名 +- ✅ 正确:20260516_DISC-011.md +- ❌ 错误:5月16日课评.md、第11周课评.md + +### 禁用词汇(课评正文) +- ❌ 补课、来补课、作为补课学生 +- ❌ 第一次上课(除非教师明确说明) +- ❌ C++、AI编程(使用标准编号) + +--- + +## 五、备份与恢复 + +### 备份位置 +``` +主文件:.claude/memory/class/{班级}/{学生}/feedback/YYYYMMDD_课程编号-课次.md +备份文件:.claude/.backup/YYYYMMDD_HHMMSS_{学生}.md +旧文件备份:原文件路径.md.bak +``` + +### 恢复流程 +1. 输入 `/恢复 {学生姓名}` +2. 从列出的备份版本中选择 +3. 确认恢复 + +--- + +## 六、待修复列表 + +### 位置 +``` +.claude/.tasks/fix-list-YYYYMMDD.md +``` + +### 查看与修复 +``` +指令:/修复 +→ 展示待修复列表 +→ 逐个处理或批量自动修复 +``` + +--- + +## 七、完整工作流程示例 + +### 高效课后流程 + +``` +1. 打开系统 + └─ /周六(或 /今天)→ 自动加载发现世界-周六09点 + +2. 加载学生模板 + └─ /模板 周四19点 → 显示学生名单 + +3. 速记输入(自动补全) + └─ 乔乔:gj5→zd3→zt ↑ ++ + 系统提示:gj5→zd3→zt ↑++ + +4. 生成课评 + └─ 并行生成 → 实时保存一份一份 + +5. 自动校验 + └─ ✅ 全部通过 ⚠️ 或 警告提示 + +6. 保存完成 + └─ 三级备份同时保存 ✅ + +7. 查看待修复 + └─ /修复 处理未完成项目 +``` + +--- + +## 八、常见问题 + +### Q: 备份会占用空间吗? +A: 自动保留最近7天备份,每月1号备份长期保留,自动清理超过时间的备份。 + +### Q: 速记符号记不住怎么办? +A: 不用记住,输入时系统会自动提示含义,按Tab键可自动补全。 + +### Q: 校验警告可以跳过吗? +A: 可以,警告不阻塞保存,但会记录在待修复列表,后续可集中处理。 + +### Q: 目录不存在怎么办? +A: 系统会自动逐级创建完整目录结构,无需手动操作。 + +--- + +## 九、情绪符号对照表 + +| 符号 | 含义 | 对应表述 | +|------|------|---------| +| `↑` | 开心/积极/投入 | 开心、投入、积极、热情、参与度高 | +| `→` | 稳定/平和/正常 | 稳定、平和、正常、专注、认真 | +| `↓` | 低落/烦躁 | 低落、烦躁、不开心、需要关注 | +| `~` | 波动/反复 | 情绪波动、反复不定 | +| `++` | 进步/提升 | 比上周好、进步明显、状态提升 | +| `↑↑` | 非常开心/兴奋 | 特别开心、非常投入、状态极佳 | +| `↓↓` | 特别低落/需要关注 | 非常低落、需要关注、情绪不好 | +| `gd` | 孤独/独自玩 | 喜欢独自玩、独自活动 | +| `jl` | 焦虑/紧张/不安 | 紧张、焦虑、不安 | + +--- + +## 十、示例速记组合 + +``` +乔乔:gj5→zd3→zt ↑++ → 观望5分钟→主动搭3层→自己调整,开心,比上周进步 +昊昊:慢热→zd3→反复调 → → 慢热,主动搭3层,反复调整,稳定 +小明:专注15→完成→分享→合作 ↔ 专注15分钟→完成→分享→合作 +``` + +--- + +*速查卡版本:v1.0.0* +*最后更新:2026-05-16* diff --git a/.claude/skills/keping-simplified/SKILL.md b/.claude/skills/keping-simplified/SKILL.md new file mode 100644 index 0000000..b66454e --- /dev/null +++ b/.claude/skills/keping-simplified/SKILL.md @@ -0,0 +1,227 @@ +--- +name: keping-simplified +description: 超级简化版课评生成器!只需输入 "/课评" 即可启动,表单直连提交,AI自动检测并生成。为穹狼乐高编程设计。 +version: 5.1.0 +author: 穹狼教学团队 +--- + +# keping-simplified — 超级简化版课评生成器 + +## 🚀 核心特点 + +**超级简单!一键启动!** +- 只需输入 `/课评` 即可启动,无需记住一堆命令 +- 启动即显示当前周数+班级选择 +- 自动匹配课程主题(基于学期周数映射表) +- 本地网页表单:学生状态快捷选择 + 速记输入 + 进度条 +- **直连提交**:表单直接 POST 到本地服务器,无需复制粘贴 +- AI 自动检测信号文件 → 生成课评 → 双轨保存 +- 完成后自动清理临时数据 + +--- + +## 📋 完整工作流程 + +### 第一步:启动(只需一个命令!) +``` +用户输入:/课评 +``` +立即执行以下操作: +1. ✅ 计算当前周数(基于3月2日开学) +2. ✅ 显示当天对应周几的班级列表 +3. ✅ 自动匹配每个班级的当周课程主题 + +--- + +### 第二步:班级选择 +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +🎯 选择班级 | 第X周 YYYY-MM-DD +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +可选班级: +[1] 发现世界-周四19点(DISC-011 鳄鱼) +[2] Wed创造世界-周六1030(CREATE-011 推磨机器人) +[3] AICODE03小Q周六1400(AICODE03-011 AI文档写作) +[4] SPIKE02-周日1030(SPIKE-011 摩天轮) +[5] 手动输入班级名称 + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` +用户选择班级后,系统自动: +1. 启动本地表单服务器(`python src/form_server.py`) +2. 读取该班级目录,加载学生名单和画像 +3. 匹配当周课程主题(从学期周数映射表) + +--- + +### 第三步:打开网页表单 + 直连提交 +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +🖥️ 表单服务器已启动! +👉 http://localhost:8088/form?class=发现世界-周四19点&week=11&course=DISC-011&theme=鳄鱼&date=2026-05-16 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +**表单已自动填入:班级、周数、日期、课程主题、学生名单(含画像摘要)** + +用户在浏览器中: +1. 为每位学生选择状态(出勤/请假/补课/体验) +2. 填写课堂表现(支持速记符号) +3. 点击「🚀 提交并保存」 +4. 看到「✅ 提交成功」→ 可关闭页面 + +**数据自动 POST 到本地服务器 → 保存为 JSON → 写入信号文件** + +**表单预览**: +``` +┌──────────────────────────────────────────┐ +│ 📝 课评填写表单 - 发现世界-周四19点 │ +│ 第11周 · DISC-011 鳄鱼 · 2026-05-16 │ +├──────────────────────────────────────────┤ +│ 📊 填写进度:3/6 · █████░░ 50% │ +├──────────────────────────────────────────┤ +│ ┌─梁昕乔───────────────────────┐ │ +│ │ 📋 性格内向,需鼓励... │ │ +│ │ [出勤] [请假] [补课] [体验] │ │ +│ │ 表现:____________________ │ │ +│ │ (速记提示:gj=观望、zd=主动) │ │ +│ └──────────────────────────────┘ │ +│ ┌─钟昀昊───────────────────────┐ │ +│ │ [出勤] [请假] [补课] [体验] │ │ +│ │ 表现:____________________ │ │ +│ └──────────────────────────────┘ │ +│ ┌─+ 添加临时学生──────────────┐ │ +│ │ 姓名:____ 状态:[补课/体验] │ │ +│ └──────────────────────────────┘ │ +├──────────────────────────────────────────┤ +│ [🚀 提交并保存] │ +└──────────────────────────────────────────┘ +``` + +--- + +### 第四步:AI 自动检测 → 生成并保存 +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +🔔 检测到表单提交 | 发现世界-周四19点 | DISC-011 鳄鱼 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +[1/3] 生成梁昕乔课评... ✅ 已保存 +[2/3] 生成钟昀昊课评... ✅ 已保存 +[3/3] 生成林瀚丞课评... ✅ 已保存 +📝 其他学生请假,不生成课评 + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +✅ 全部完成!已保存 3 人 | 请假 2 人 +🗑️ 已清理临时数据文件 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +点击「提交」后: +1. ✅ 数据自动 POST 到本地服务器 +2. ✅ 服务器保存为 `.claude/.tmp/evaluation_input_{班级}.json` +3. ✅ 写入信号文件 `EVALUATION_READY.txt` +4. ✅ AI 检测到信号,读取 JSON 数据 +5. ✅ 批量生成所有学生课评(180-350字三段式) +6. ✅ 自动保存到标准路径(双轨) +7. ✅ 清理临时数据文件 + +--- + +## 📋 课评生成规则 + +### 学生状态处理 +- **出勤** → 正常生成课评,保存到 `feedback/` +- **请假** → 仅生成请假记录 `(请假).md` +- **补课** → 保存到 `补课/feedback/` +- **体验** → 保存到 `补课/feedback/` + +### 三段式结构(固定不变) +``` +第1段(30-55字):课程知识点,末尾1个emoji +第2段(100-220字,弹性):掌握+环节+亮点,1-3个emoji分散插入 +第3段(30-55字):课后建议,末尾1个emoji +``` + +### 称呼规则 +- 优先用小名/昵称 +- 其次用去姓称名 +- 单字名叠字化 + +### Emoji规则 +- 第1段:🔍 💡 ⚙️(根据课程类型) +- 第2段:💪 ✨ 📈 🎯(根据亮点) +- 第3段:🏠 🔧(根据建议) + +--- + +## 💾 自动保存规则 + +### 文件路径(课评规范V1.0标准) +``` +.claude/memory/class/{班级}/ +├── summaries/YYYYMMDD_{课程编号}_{班级反馈}.md +├── {学生}/ +│ └── feedback/YYYYMMDD_{课程编号}_{课次}.md +└──补课/{学生}/ + └── feedback/YYYYMMDD_{课程编号}.md +``` + +### 无需确认,自动保存! +课评生成后立即保存,无需教师点击确认。 + +--- + +## 📊 速记符号对照表 + +| 速记 | 含义 | +|------|------| +| gj# | 观望#分钟 | +| zd# | 主动搭#层 | +| zt | 自己调整 | +| wb | 完成 | +| ↑ | 开心 | +| → | 稳定 | +| ++ | 比上周进步 | +| -- | 需关注 | + +--- + +## 📝 触发方式 + +**主触发词:** +- `/课评` → 启动超级简化流程 +- `/keping-simple` → 别名 + +**不触发其他技能:** +- 不要触发 `keping-advanced` 或 `keping-optimizer` + +--- + +## ⚙️ 关键配置 + +### 学期周数计算基准 +- 开学日期:2026年3月2日 +- 周数公式:Floor((当天-3月2日)/7) +1 + +### 班级目录路径 +``` +.claude/memory/class/{班级名称}/ +``` + +--- + +## ✅ 质量检查清单 +- [ ] 字数:180-350(根据输入丰富度) +- [ ] 三段式结构完整 +- [ ] Emoji位置正确(段末/分散插入) +- [ ] 称呼正确(不用全名) +- [ ] 无周数显示(正文) +- [ ] 路径符合课评规范V1.0 + +--- + +*版本:v5.1.0(表单直连提交)* +*维护者:穹狼教学团队* +*最后更新:2026-05-20* diff --git a/.claude/skills/keping-simplified/assets/form_template.html b/.claude/skills/keping-simplified/assets/form_template.html new file mode 100644 index 0000000..9f15f64 --- /dev/null +++ b/.claude/skills/keping-simplified/assets/form_template.html @@ -0,0 +1,232 @@ + + + + + +课评填写表单 - 穹狼乐高编程 + + + +
+
+

📝 课评填写表单

+
班级:发现世界-周四19点 | 第11周 | 2026-05-16
+
+
+
0/5 完成
+
+
+
+
+
+
📚 课程目标:DISC-011 蜥蜴
+
+核心知识点:关节连接、可动结构、仿生设计
+课时长度:60分钟 +
+
+
+
+ 添加临时学生(补课/体验)
+
+ +
+
+
+ + + \ No newline at end of file diff --git a/.claude/skills/keping-simplified/config.json b/.claude/skills/keping-simplified/config.json new file mode 100644 index 0000000..ccea31b --- /dev/null +++ b/.claude/skills/keping-simplified/config.json @@ -0,0 +1,34 @@ +{ + "name": "keping-simplified", + "skill_name": "keping-simplified", + "version": "5.0.0", + "description": "超级简化版课评生成器!只需输入 \"/课评\" 即可启动,一键生成,自动保存。支持周数选择、班级选择、学生状态选择、速记输入、进度条显示。为穹狼乐高编程设计。", + "triggers": [ + "/课评", + "/keping-simple", + "/简单课评", + "生成课评", + "写课评" + ], + "semester_config": { + "baseline_date": "2026-03-02", + "week_calculation": "Floor((current_date - 2026-03-02) / 7) + 1", + "total_weeks": 20, + "current_week": 11, + "current_date": "2026-05-17" + }, + "class_types": { + "DISC": { "prefix": "DISC", "age_group": "preschool", "style": "warm" }, + "CREATE": { "prefix": "CREATE", "age_group": "preschool", "style": "warm" }, + "INVENT": { "prefix": "INVENT", "age_group": "preschool", "style": "warm" }, + "TUBE": { "prefix": "TUBE", "age_group": "preschool", "style": "warm" }, + "SPIKE": { "prefix": "SPIKE", "age_group": "elementary", "style": "concise" }, + "AICODE03": { "prefix": "AICODE03", "age_group": "elementary", "style": "technical" }, + "CSP": { "prefix": "CSP", "age_group": "elementary", "style": "technical" } + }, + "paths": { + "class_root": ".claude/memory/class", + "lesson_root": ".claude/memory/lesson", + "template": ".claude/skills/keping-simplified/assets/form_template.html" + } +} diff --git a/.claude/skills/keping-simplified/references/generation_rules.md b/.claude/skills/keping-simplified/references/generation_rules.md new file mode 100644 index 0000000..cc30524 --- /dev/null +++ b/.claude/skills/keping-simplified/references/generation_rules.md @@ -0,0 +1,285 @@ +# keping-simplified — 生成规则详解 + +## 1️⃣ 启动流程规则 + +### 第一步:响应 /课评 命令 + +当用户输入 `/课评`,立即启动简化流程。**跳过任何其他判断**。 + +```python +用户输入:/课评 +→ 执行:启动简化流程 +→ 目标:一周数+日期选择界面 +``` + +--- + +## 2️⃣ 周数与日期计算规则 + +### 基准设置 +- **学期开学日**:2026-03-02(第1周周一) +- **当前日期**:自动获取今天的日期 +- **周数计算公式**: + ``` + 周数 = Floor((当前日期 - 2026-03-02) / 7) + 1 + ``` + +### 日期选择界面示例 + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +📅 第11周 | 选择日期 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +当前日期:2026-05-16 + +请选择周几: +[1] 周一 +[2] 周二 +[3] 周三 +[4] 周四 +[5] 周五 +[6] 周六 +[7] 周日 + +[其他日期] 手动输入 YYYY-MM-DD +``` + +### 用户选择后 +- 根据周几推算具体日期(基于当前周) +- 进入班级选择 + +--- + +## 3️⃣ 班级选择规则 + +### 读取班级列表 +1. 扫描 `.claude/memory/class/` 目录 +2. 列出所有班级文件夹名称 +3. 按字母/时间排序显示 + +### 界面示例 + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +🎯 选择班级 | 第11周 · 2026-05-16 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +可选班级: +[1] 发现世界-周四19点 +[2] Wedo创造世界-周六1030 +[3] AICODE03小Q周六1400 +[4] SPIKE02-周日1030 +[5] 手动输入班级名称 +``` + +--- + +## 4️⃣ 课程目标加载规则 + +### 策略 A:找到课程教案(优先) + +按顺序查找: +1. 班级目录下是否有历史课程记录 +2. memory/lesson/ 目录下查找第X周课程 +3. 基于班级类型匹配课程编号 + +**匹配成功后显示:** +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +📚 课程目标确认 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +课程代码:DISC-011 +课程主题:蜥蜴 +核心知识点:关节连接、可动结构、仿生设计 +课时长度:60分钟 + +[1] 确认使用这个 +[2] 修改课程目标 +``` + +### 策略 B:没找到课程教案(降级) + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +⚠️ 未找到课程教案,请手动输入 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +请填写本周课程目标: +课程主题: +核心知识点: +[1] 跳过,用通用模板 +[2] 保存为常用课程 +``` + +--- + +## 5️⃣ HTML 表单启动规则 + +### 创建并打开表单 + +1. 复制模板 `assets/form_template.html` +2. 替换占位符: + - `CLASS_NAME` → 班级名 + - `WEEK_NUM` → 周数 + - `DATE_STR` → 日期 + - `COURSE_CODE` → 课程代码 + - `COURSE_TITLE` → 课程主题 + - `STUDENTS_LIST` → 学生JSON +3. 保存为临时文件(例如 `temp_form_YYYYMMDD_HHMMSS.html`) +4. 自动在浏览器打开 + +### 学生列表加载 + +从班级目录读取: +- `.claude/memory/class/{班级}/` 下的子文件夹 +- 每个子文件夹是一个学生 +- 读取 `profile.md` 获取小名/昵称(如果有) + +```json +{ +"students": [ +{ "name": "梁家铭", "nickname": null }, +{ "name": "简思瑜", "nickname": "小鱼" }, +... +] +} +``` + +--- + +## 6️⃣ 速记符号解析规则 + +### 速记对照表 + +| 速记 | 解析为中文描述 | +|------|--------------| +| `gj#` | 观望#分钟 | +| `zd#` | 主动搭#层 | +| `zt` | 自己调整 | +| `wb` | 完成 | +| `zx#` | 专注#分钟 | +| `sb#` | 失败#次后调整 | +| `ts#` | 探索#分钟 | +| `cz#` | 创造#种方案 | +| `wt#` | 提问#次 | +| `hz` | 合作 | +| `fx` | 分享 | +| `tq` | 求助 | +| `mr` | 融入 | +| `ms` | 模仿 | +| `jy` | 建议给同伴 | +| `bd` | 被带动 | +| `zl` | 孤立/独自 | +| `cq` | 冲突/争执 | +| `↑` or `kx` | 开心 | +| `→` or `wd` | 稳定 | +| `↓` or `fd` | 烦躁/低落 | +| `~` or `bd` | 情绪波动 | +| `↑↑` or `kc` | 非常开心/兴奋 | +| `→→` or `wa` | 非常稳定/沉浸 | +| `gd` | 孤独/独自玩 | +| `jl` | 焦虑/紧张 | +| `++` | 比上周进步 | +| `--` | 需关注 | + +### 解析示例 + +``` +输入:gj5→zd3→zt ↑++ +解析:观望5分钟后主动搭3层,自己调整,开心,比上周进步 +``` + +--- + +## 7️⃣ 课评生成规则 + +### 三段式结构(固定不变) + +**第1段(课程知识点,30-55字):** +- 包含:主题、1-2个核心知识点 +- 末尾1个emoji:🔍 💡 ⚙️(根据类型) + +**第2段(课堂细节,100-220字,弹性):** +- 整合:掌握程度+环节表现+成长亮点 +- emoji:1-3个,自然分散插入 + +**第3段(课后建议,30-55字):** +- 具体可操作的家庭活动 +- 末尾1个emoji:🏠 🔧 + +### 字数弹性规则 + +| 输入丰富度 | 目标字数范围 | +|----------|-----------| +| 很简洁(只有1-2个速记)| 180-220 | +| 中等(3-5个速记)| 220-280 | +| 详细(5个以上+情绪+对比)| 280-350 | + +### 称呼规则 + +1. 优先用小名/昵称(从 `profile.md` 读取) +2. 其次用去姓称名(双字名 → 去掉姓) +3. 单字名 → 叠字化 + +### Emoji 分配 + +| 位置 | 表情库 | +|------|-------| +| 第1段末尾 | 🔍 💡 ⚙️ | +| 第2段亮点处 | 💪 ✨ 📈 🎯 🤝 😊 | +| 第3段末尾 | 🏠 🔧 | + +--- + +## 8️⃣ 保存规则 + +### 文件路径标准 + +``` +.claude/memory/class/{班级名称}/ +├── summaries/ +│ └── YYYYMMDD_{课程代码}_{班级反馈}.md +├── {学生姓名}/ +│ └── feedback/ +│ └── YYYYMMDD_{课程代码}_{课次}.md +└──补课/{学生姓名}/ + └── feedback/ + └── YYYYMMDD_{课程代码}.md +``` + +### 学生类型-保存路径映射 + +| 学生状态 | 保存位置 | +|---------|--------| +| 出勤 | {班级}/{学生}/feedback/ | +| 请假 | {班级}/{学生}/feedback/(带 `(请假)` 标记)| +| 补课 | {班级}/补课/{学生}/feedback/ | +| 体验 | {班级}/补课/{学生}/feedback/ | + +### 自动保存时机 + +课评生成完成后立即保存,无需教师确认。 + +--- + +## 9️⃣ 请假/补课/体验处理 + +### 请假 +- 生成:请假记录文件 +- 路径:`feedback/YYYYMMDD_{课程编号}(请假).md` +- 内容:简洁说明请假 + +### 补课 +- 路径:`补课/{学生}/feedback/YYYYMMDD_{课程编号}.md` +- 课评正文:不提及"补课"二字 +- 文件名:可标记来源 + +### 体验 +- 路径:`补课/{学生}/feedback/YYYYMMDD_{课程编号}.md` +- 课评:正常写(不提"体验") + +--- + +*最后更新:2026-05-16* diff --git a/.claude/skills/keping-simplified/快速参考卡.md b/.claude/skills/keping-simplified/快速参考卡.md new file mode 100644 index 0000000..3403e84 --- /dev/null +++ b/.claude/skills/keping-simplified/快速参考卡.md @@ -0,0 +1,67 @@ +# 🚀 keping-simplified — 快速参考卡 + +## 💡 如何启动(只需一个命令!) +``` +输入:/周六(或 /课评) +``` + +## 📋 完整流程(v5.0 直连提交版) +``` +1️⃣ /周六 + ↓ +2️⃣ 选择班级(已显示当周课程主题) + ↓ +3️⃣ 打开浏览器表单 → 填写学生表现 → 点击「提交并保存」 + ↓ (数据 POST 到本地服务器,无需复制粘贴!) +4️⃣ AI 自动检测信号文件 → 生成课评 → 双轨保存 + ↓ +5️⃣ 完成!🗑️ 自动清理临时文件 +``` + +## ⌨️ 速记符号(最常用的) +| 速记 | 含义 | +|------|------| +| gj# | 观望#分钟 | +| zd# | 主动搭#层 | +| zt | 自己调整 | +| ↑ | 开心 | +| → | 稳定 | +| ++ | 比上周进步 | + +## 📂 保存路径(自动) +``` +.claude/memory/class/{班级}/ +├── summaries/ +│ └── YYYYMMDD_{课程}_班级反馈.md +├── {学生}/ +│ └── feedback/ +│ └── YYYYMMDD_{课程}.md +└──补课/{学生}/ + └── feedback/ + └── YYYYMMDD_{课程}.md +``` + +## ⚙️ 四段式结构(输出固定) +| 段落 | 内容 | 字数 | Emoji | +|------|------|------|------| +| 1️⃣ | 课程知识点 | 30-55 | 1个末尾 | +| 2️⃣ | 掌握程度与操作细节 | 80-150 | 1-2个分散插入 | +| 3️⃣ | 课堂亮点与成长 | 60-120 | 1-2个分散插入 | +| 4️⃣ | 课后建议 | 30-55 | 1个末尾 | + +**总字数**:标准版 220-300字,详细版 300-400字 +**总Emoji数**:3-5个 + +## 🎨 Emoji 使用规范 + +**总数量**:每篇课评使用 **3-5个** Emoji + +| 位置 | 数量 | 用途 | 推荐表情 | +|------|:----:|------|----------| +| 第1段(知识点) | 1个 | 段尾点缀 | 🔍 💡 ⚙️ 🎯 | +| 第2段(掌握与操作) | 1-2个 | 分散插入 | 💪 ✨ 📈 🤝 | +| 第3段(亮点与成长) | 1-2个 | 分散插入 | 😊 🌟 💫 🎉 | +| 第4段(建议) | 1个 | 段尾点缀 | 🏠 🔧 📚 | + +--- +*版本:v5.0 | 最后更新:2026-05-22* diff --git a/.gitignore b/.gitignore index 25ae0df..d0bd2b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,12 @@ # 环境变量文件(包含敏感信息) .env +# Python +__pycache__/ +*.pyc +*.pyo +*.egg-info/ + # 其他常见忽略项 *.log *.tmp diff --git a/.trae/skills/课评/SKILL.md b/.trae/skills/课评/SKILL.md new file mode 100644 index 0000000..1ede9a4 --- /dev/null +++ b/.trae/skills/课评/SKILL.md @@ -0,0 +1,151 @@ +--- +name: "课评" +description: "穹狼乐高编程课评生成Skill。当用户输入/课评时启动,帮助教师快速生成个性化课后评价。支持班级选择、学生状态标记、课堂表现记录,自动生成180-350字三段式课评并自动保存。适用于幼儿积木、少儿编程、机器人等多种课程类型。" +version: "1.0.0" +author: "穹狼教学团队" +--- + +# 课评 - 课后评价生成器 + +## 🚀 快速开始 + +**触发方式**:输入 `/课评` 即可启动 + +系统会立即执行: +1. 计算当前教学周数(基于2026年3月2日开学) +2. 显示当天所有可选班级 +3. 自动匹配各班级的当周课程主题 + +--- + +## 📋 使用流程 + +### 第一步:选择班级 + +输入 `/课评` 后,系统显示: + +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +🎯 选择班级 | 第X周 YYYY-MM-DD +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +可选班级: +[1] 发现世界-周四19点(DISC-011 鳄鱼) +[2] Wedo创造世界-周六1030(CREATE-011 推磨机器人) +[3] AICODE03小Q周六1400(AICODE03-011 AI文档写作) +[4] SPIKE02-周日1030(SPIKE-011 摩天轮) +[5] 手动输入班级名称 + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +### 第二步:填写学生表现 + +选择班级后,系统显示该班级所有学生: + +``` +┌─ 学生1: 乔乔 ─────────────────────────┐ +│ 状态:[✅出勤] [🚫请假] [📝体验] [🔄补课] │ +│ 表现:_____________________________ │ +└──────────────────────────────────────────┘ + +┌─ 学生2: 昊昊 ─────────────────────────┐ +│ 状态:[✅出勤] [🚫请假] [📝体验] [🔄补课] │ +│ 表现:_____________________________ │ +└──────────────────────────────────────────┘ +``` + +**速记符号**(可在表现描述中使用): +| 速记 | 含义 | +|------|------| +| gj# | 观望#分钟 | +| zd# | 主动搭#层 | +| zt | 自己调整 | +| wb | 完成 | +| ↑ | 开心 | +| → | 稳定 | +| ++ | 比上周进步 | +| -- | 需关注 | + +### 第三步:一键生成 + +确认后,系统自动: +1. 为每位出勤学生生成个性化课评 +2. 自动保存到对应目录 +3. 生成班级总结 + +--- + +## 📝 课评格式 + +### 三段式结构 + +``` +第1段(30-55字):课程知识点,末尾1个emoji +第2段(100-220字):掌握程度+课堂表现+成长亮点,1-3个emoji +第3段(30-55字):课后建议,末尾1个emoji +``` + +### 称呼规则 +- 优先使用小名/昵称 +- 其次使用去姓称名 +- 单字名使用叠字(如"昊"→"昊昊") + +### Emoji规则 +- 第1段:🔍 💡 ⚙️(根据课程类型) +- 第2段:💪 ✨ 📈 🎯(根据亮点) +- 第3段:🏠 🔧(根据建议) + +--- + +## 💾 保存规则 + +### 文件路径 +``` +.claude/memory/class/{班级}/ +├── summaries/YYYYMMDD_{课程编号}_{班级反馈}.md +├── {学生}/ +│ └── feedback/YYYYMMDD_{课程编号}_{课次}.md +└── 补课/{学生}/ + └── feedback/YYYYMMDD_{课程编号}.md +``` + +### 学生状态处理 +- **出勤** → 正常生成课评,保存到 `feedback/` +- **请假** → 仅生成请假记录 `(请假).md` +- **补课** → 保存到 `补课/feedback/` +- **体验** → 保存到 `补课/feedback/` + +--- + +## ⚙️ 配置信息 + +### 学期周数计算 +- 开学日期:2026年3月2日 = 第1周 +- 计算公式:`周数 = Floor((当前日期 - 3月2日) / 7) + 1` + +### 课程编号规范 +- 发现世界:DISC-XXX +- 发明世界:INVENT-XXX +- 创造世界:CREATE-XXX +- 动力机械:MECH-XXX +- SPIKE:SPIKE-XXX +- AI编程:AICODE03-XXX + +--- + +## ✅ 质量检查 + +生成后自动检查: +- [ ] 字数180-350字 +- [ ] 三段式结构完整 +- [ ] Emoji位置正确 +- [ ] 称呼正确(不用全名) +- [ ] 无周数显示在正文中 +- [ ] 路径符合规范 + +--- + +*版本:v1.0.0* +*维护者:穹狼教学团队* +*最后更新:2026-05-23* diff --git a/CLAUDE.md b/CLAUDE.md index af6cce0..9fc701d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,7 +1,11 @@ # 穹狼乐高编程AI课评生成系统 > 为2.5岁-小学4年级学生自动生成个性化课程评价 -> 版本:v4.0(课评规范同步版)| 规则文件:9个核心文件 + 20个归档规则 +> 版本:v4.5.1(AICODE03课程更新)| 规则文件:9个核心文件 + 20个归档规则 +> +> **课程匹配规则**:根据当周日期自动匹配课程主题(基于学期周数映射表),不参考上节课进度 +> +> **v4.5 表单直连**:网页表单直接 POST 到本地服务器(`src/form_server.py`),AI 检测信号文件自动处理,彻底取消复制粘贴步骤 > > **合规说明**:本仓库已同步 [课评规范V1.0](课评规范V1.0.md) 全部要求,包括课程编号规范、目录结构规范、课评文件命名规范、课评完成率统计规则。确保自动统计系统可正确识别到课评。 > @@ -192,6 +196,30 @@ classfeedback/ ## 处理流程 +### 模式一:交互式模式(推荐) + +> 适用于所有上课日(周一~周日),以下以周六为例 + +``` +/周六(或 /今天)→ 展示班级列表(含当周课程主题)→ 选择班级 + ↓ + 启动本地表单服务器 + 自动匹配当周课程 + ↓ + 打开浏览器表单 → 填写 → 点击「提交并保存」 + ↓ + 数据 POST 到服务器 → 保存 JSON + 信号文件 + ↓ + AI 检测信号 → 读取 JSON → 批量生成 → 双轨保存 + ↓ + 🗑️ 清理临时数据 → 完成 +``` + +> **课程匹配说明**:系统根据当前日期计算学期周数,直接匹配当周课程主题(如第11周→DISC-011 蜥蜴),不参考上节课进度。除非教师特别说明补课,否则一律使用当周标准课程主题。 + +> 友好的多轮对话引导,支持 `/周几` 快速索引 + Form-First 网页表单(含进度条、填写状态、一键复制、补课/体验学生区)。详见 [20-workflow.md 第14节](.claude/rules/20-workflow.md) + +### 模式二:批量输入模式 + ``` 教师极简输入 → AI解析 → 生成个性化课评 → 【自动双轨保存】 ↓ @@ -238,6 +266,15 @@ classfeedback/ ### 快捷指令 +#### 模式选择 +| 指令 | 功能 | +|:-----|:-----| +| **`/周几`** | **按上课日快速索引(推荐)**,如 `/周六`、`/周日`、`/周四` | +| `/今天` | 自动判断当天星期几,启动交互式流程 | +| `/交互式` | 启用交互式课评生成模式(默认,Form-First 网页表单) | +| `/批量` | 启用批量输入模式(一次性输入所有学生) | + +#### 课评操作 | 指令 | 功能 | |:-----|:-----| | `查看出勤` | 查看本周各班级出勤(读取汇总头部) | @@ -248,6 +285,10 @@ classfeedback/ ## 版本历史 +- **v4.5.1** | 2026-05-20 | AICODE03课程全面更新:同步最新教学大纲(AI原理、大作家系列、个人主页、俄罗斯方块、涂鸦PK、Skills入门等1-20周完整课程) +- **v4.5** | 2026-05-20 | 表单直连提交:网页表单直接 POST 到本地服务器(`src/form_server.py`),AI 检测信号文件自动生成课评,彻底取消复制粘贴步骤;新增临时数据清理机制 +- **v4.4** | 2026-05-16 | Form-First 交互式流程优化:课程进度自动推演(改为根据当周日期匹配课程主题,不参考上节课进度)、默认网页表单(Form-First)、表单直连提交、新增项目记忆文件 +- **v4.3** | 2026-05-16 | 交互式流程优化:新增 `/周几` 快速索引指令;B模式分开展示学生 + 独立输入区 + 快捷标记按钮(请假/体验/补课/出勤) - **v4.0** | 2026-05-14 | 同步课评规范V1.0:新增课程编号规范(CSP/AICODE)、新目录结构(`.claude/memory/class/`)、文件命名规范(`YYYYMMDD_课程编号-课次.md`)、课评完成率统计规则 - **v3.1** | 2026-05-05 | 简化保存流程:删除"待确认"状态,改为"生成即双轨保存";出勤嵌入班级汇总 - **v2.5** | 2026-05-01 | 统一字数弹性范围180-350字 diff --git a/src/README_课评保存工具使用说明.md b/src/README_课评保存工具使用说明.md new file mode 100644 index 0000000..943bb39 --- /dev/null +++ b/src/README_课评保存工具使用说明.md @@ -0,0 +1,241 @@ +# 课评保存自动化工具使用说明 + +## 工具概述 + +`evaluation_saver.py` 是一个自动化工具,用于帮助教师按照课评规范V1.0的要求保存学生课评,实现双轨保存机制。 + +**功能特性**: +- ✅ 自动创建标准目录结构 +- ✅ 智能识别学生档案位置 +- ✅ 支持补课学生跨班级双向记录 +- ✅ 自动计算学期周数和课程主题 +- ✅ 交互式输入模式(适合单次生成) +- ✅ 配置文件批量处理模式(适合批量保存) +- ✅ 完整的错误处理和提示 + +## 快速开始 + +### 前置条件 + +- Python 3.7 或更高版本 +- 项目根目录为 `e:\classfeedback`(或你的实际位置) + +### 基本用法 + +#### 1. 交互式模式(推荐新手使用) + +在项目根目录下运行: + +```bash +cd e:\classfeedback +python src\evaluation_saver.py +``` + +按照提示依次输入: + +1. 班级名称(如:`AICODE03小Q周五1900`) +2. 授课日期(如:`2026-05-16`,默认是今天) +3. 课程代码(如:`AICODE03-011`) +4. 学生姓名(如:`谢善诺`) +5. 课评内容(可以粘贴多行文本,用空行结束) +6. 是否是补课学生(y/n) +7. 如果是补课,输入原班级名称 + +工具会自动处理保存,并告诉你保存的文件位置。 + +#### 2. 配置文件批量模式(推荐批量使用) + +1. 复制配置示例文件: + +```bash +copy src\config_example.json src\my_config.json +``` + +2. 编辑 `my_config.json`,填入你的班级信息和学生课评 + +3. 运行批量保存: + +```bash +python src\evaluation_saver.py --config src\my_config.json +``` + +## 配置文件说明 + +配置文件是 JSON 格式,包含以下字段: + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|------|------|:----:|------|------| +| `class_name` | string | ✅ | 班级名称 | `"AICODE03小Q周五1900"` | +| `teaching_date` | string | ✅ | 授课日期(格式:YYYY-MM-DD) | `"2026-05-16"` | +| `course_code` | string | ✅ | 课程代码 | `"AICODE03-011"` | +| `students` | array | ✅ | 学生列表 | - | +| `students[].name` | string | ✅ | 学生姓名 | `"谢善诺"` | +| `students[].evaluation_text` | string | ✅ | 课评内容 | `"..."` | +| `students[].is_makeup` | boolean | ❌ | 是否是补课学生(默认false) | `false` | +| `students[].original_class` | string | ❌ | 原班级名称(仅补课学生需要) | `"AICODE03小Q周六1400"` | + +### 配置示例 + +#### 示例1:单个正式学生 + +```json +{ + "class_name": "AICODE03小Q周五1900", + "teaching_date": "2026-05-16", + "course_code": "AICODE03-011", + "students": [ + { + "name": "谢善诺", + "evaluation_text": "谢善诺本节课学习了\"超能力抽签机\"项目...", + "is_makeup": false + } + ] +} +``` + +#### 示例2:混合正式学生和补课学生 + +```json +{ + "class_name": "AICODE03小Q周六1400", + "teaching_date": "2026-05-17", + "course_code": "AICODE03-011", + "students": [ + { + "name": "黄榆斐", + "evaluation_text": "黄榆斐本节课学习了\"超能力抽签机\"项目...", + "is_makeup": false + }, + { + "name": "谢善诺", + "evaluation_text": "谢善诺本节课学习了\"超能力抽签机\"项目...", + "is_makeup": true, + "original_class": "AICODE03小Q周五1900" + } + ] +} +``` + +## 目录结构规范 + +工具会自动创建和管理以下目录结构(符合课评规范V1.0): + +``` +.claude/memory/class/ +├── {班级名称}/ +│ ├── summaries/ # 班级总结目录 +│ │ └── YYYYMMDD_课程编号-课次_班级反馈.md +│ ├── {学生姓名}/ # 正式学生目录 +│ │ ├── feedback/ # 个人课评目录 +│ │ │ ├── YYYYMMDD_课程编号-课次.md +│ │ │ ├── YYYYMMDD_课程编号-课次(请假).md +│ │ │ └── YYYYMMDD_课程编号-课次(补课-去班级名).md +│ │ └── profile.md # 学生画像 +│ └── 补课/ # 补课学生专用目录 +│ └── {学生姓名}/ +│ └── feedback/ +│ └── YYYYMMDD_课程编号.md +└── ... +``` + +## 文件命名规范 + +| 文件类型 | 命名格式 | 示例 | +|---------|---------|------| +| 正常课评 | `YYYYMMDD_课程编号-课次.md` | `20260516_AICODE03-011.md` | +| 请假记录 | `YYYYMMDD_课程编号-课次(请假).md` | `20260516_AICODE03-011(请假).md` | +| 补课追踪 | `YYYYMMDD_课程编号-课次(补课-去班级名).md` | `20260516_AICODE03-011(补课-去AICODE03小Q周六1400).md` | +| 补课班级课评 | `YYYYMMDD_课程编号.md`(放在 `补课/{学生}/feedback/`) | `20260516_AICODE03-011.md` | + +## 补课学生处理规则 + +### 场景1:本班学生补课 + +**条件**:学生档案在当前班级 `{班级}/{学生}/` 存在 + +**处理**: +- 课评保存到:`{班级}/{学生}/feedback/YYYYMMDD_课程编号-课次.md` +- 不需要在 `补课/` 目录保存 + +### 场景2:跨班级补课(档案在其他班级) + +**条件**:学生档案在其他班级存在 + +**处理**(双向记录): +1. **补课班级侧**:保存到 `{补课班级}/补课/{学生}/feedback/YYYYMMDD_课程编号.md` + - 文件开头会自动添加:`(补课,来自{原班级})` +2. **原班级侧**:保存到 `{原班级}/{学生}/feedback/YYYYMMDD_课程编号-课次(补课-去{补课班级}).md` + - 内容是简洁的补课追踪记录 + +### 场景3:完全无档案的新学生 + +**条件**:任何班级都没有学生档案 + +**处理**: +- 询问用户选择: + 1. 仅保存到当前班级的 `补课/` 目录 + 2. 创建新档案(在当前班级创建 `profile.md`) + +## 命令行参数 + +| 参数 | 说明 | 示例 | +|------|------|------| +| `--config ` | 使用配置文件批量处理 | `--config src\my_config.json` | +| `--help` | 显示帮助信息 | `--help` | + +## 常见问题 + +### Q: 如何获取课评内容? + +A: 你可以先使用 `/课评` 指令让 Claude 生成课评,然后把生成的课评内容复制到工具中。 + +### Q: 工具会覆盖已存在的课评文件吗? + +A: 是的,如果文件已存在会被覆盖。建议在运行前备份重要文件。 + +### Q: 课程代码如何确定? + +A: 课程代码必须与校宝排课系统中的 `class_name` 一致。常见格式: +- `CSP01-07`、`CSP02-05`、`CSP05-10`(C++信息学奥赛) +- `AICODE01-01`、`AICODE03-011`、`AICODE04-08`(AI编程) +- `DISC-007`、`SPIKE-011`(乐高课程,暂不纳入自动统计) + +### Q: 学期周数是如何计算的? + +A: 学期从2026年3月2日(第1周)开始,工具会根据授课日期自动计算: +- 2026-03-02 ~ 2026-03-08 → 第1周 +- 2026-03-09 ~ 2026-03-15 → 第2周 +- ... +- 2026-05-11 ~ 2026-05-17 → 第11周 + +### Q: 遇到错误怎么办? + +A: 工具会显示友好的错误提示,常见错误: +- 班级目录不存在 → 工具会自动创建 +- JSON配置格式错误 → 检查括号、逗号、引号是否匹配 +- 日期格式错误 → 确保使用 YYYY-MM-DD 格式 + +## 实际工作流程建议 + +### 课后快速保存流程 + +1. 使用 `/课评` 指令让 Claude 批量生成课评 +2. 复制生成的课评内容 +3. 运行 `python src\evaluation_saver.py` +4. 按照提示输入班级信息和粘贴课评 +5. 重复步骤3-4直到所有学生保存完成 + +### 批量处理流程(推荐) + +1. 使用 `/课评` 指令让 Claude 批量生成课评 +2. 把所有课评整理到一个 JSON 配置文件中 +3. 运行 `python src\evaluation_saver.py --config src\my_config.json` +4. 检查保存结果 + +## 技术支持 + +如有问题,请检查: +1. Python 版本是否 >= 3.7 +2. 当前工作目录是否在项目根目录 +3. JSON 配置文件格式是否正确 +4. 班级名称、课程代码是否符合规范 diff --git a/src/config_example.json b/src/config_example.json new file mode 100644 index 0000000..df141af --- /dev/null +++ b/src/config_example.json @@ -0,0 +1,18 @@ +{ + "class_name": "AICODE03小Q周五1900", + "teaching_date": "2026-05-16", + "course_code": "AICODE03-011", + "students": [ + { + "name": "谢善诺", + "evaluation_text": "谢善诺本节课学习了\"超能力抽签机\"项目,重点练习了随机算法的实现和视觉美化技巧。\n\n这节课善诺启动状态很好,全程保持专注投入约45分钟。随机数生成的逻辑理解得很快,第一次尝试就写出了正确的循环结构。遇到界面显示问题时会主动调试参数,反复测试了5次才找到最佳的动画效果。和上周相比,本节课会主动给代码加注释,每个功能块都有清晰的说明,这个习惯非常好。最后分享时能清晰讲解自己的设计思路,表达能力进步很大。\n\n回家后可以试试给抽签机加一个\"历史记录\"功能,需要用到列表存储,下节课我们会继续学习列表相关内容。", + "is_makeup": false + }, + { + "name": "黄榆斐", + "evaluation_text": "黄榆斐本节课学习了\"超能力抽签机\"项目,重点练习了随机算法的实现和视觉美化技巧。\n\n这节课榆斐专注度很好,对随机算法特别感兴趣,自己主动尝试了3种不同的随机范围设置。界面设计很有创意,给每个超能力都配了不同的颜色和图标。遇到bug时会先自己读错误提示,实在不行才求助,这个独立解决问题的过程很重要。和前几节课相比,本节课代码规范度提升很多,缩进整齐,变量名清晰。\n\n回家后可以试试把今天的程序分享给家人,让他们也来抽个超能力,观察不同人的选择有什么规律。", + "is_makeup": true, + "original_class": "AICODE03小Q周六1400" + } + ] +} diff --git a/src/evaluation_saver.py b/src/evaluation_saver.py new file mode 100644 index 0000000..2d03528 --- /dev/null +++ b/src/evaluation_saver.py @@ -0,0 +1,587 @@ + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +穹狼乐高编程课评自动双轨保存工具 +版本:v4.0(课评规范V1.0同步版) + +功能: +1. 自动检测学生档案位置 +2. 自动保存个人课评文件到正确路径 +3. 自动处理补课学生的双向记录 +4. 自动更新班级汇总文件 +5. 支持交互式输入和批量处理 + +使用方法: + python evaluation_saver.py -i + python evaluation_saver.py --config config.json +""" + +import sys +import io +import re +import json +import argparse +from pathlib import Path +from datetime import datetime, date +from typing import Dict, List, Optional, Tuple + +# 设置UTF-8输出编码 +sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') +sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') + +# ============ 配置项 ============ + +# 基础路径配置 +BASE_PATH = Path(__file__).parent.parent +CLASS_DATA_PATH = BASE_PATH / '.claude' / 'memory' / 'class' + +# 周数计算基准 +SEMESTER_START_DATE = date(2026, 3, 2) + +# 课程代码映射(周数->课程代码) +WEEK_TO_COURSE = { + 'DISC': { + 1: 'DISC-001', 2: 'DISC-002', 3: 'DISC-003', + 4: 'DISC-004', 5: 'DISC-005', 6: 'DISC-006', + 7: 'DISC-007', 8: 'DISC-008', 9: 'DISC-009', + 10: 'DISC-010', 11: 'DISC-011', 12: 'DISC-012', + 13: 'DISC-013', 14: 'DISC-014', 15: 'DISC-015', + 16: 'DISC-016', 17: 'DISC-017', 18: 'DISC-018', + 19: 'DISC-019', 20: 'DISC-020', + }, + 'SPIKE': { + 1: 'SPIKE-001', 2: 'SPIKE-002', 3: 'SPIKE-003', + 4: 'SPIKE-004', 5: 'SPIKE-005', 6: 'SPIKE-006', + 7: 'SPIKE-007', 8: 'SPIKE-008', 9: 'SPIKE-009', + 10: 'SPIKE-010', 11: 'SPIKE-011', 12: 'SPIKE-012', + 13: 'SPIKE-013', 14: 'SPIKE-014', 15: 'SPIKE-015', + 16: 'SPIKE-016', 17: 'SPIKE-017', 18: 'SPIKE-018', + 19: 'SPIKE-019', 20: 'SPIKE-020', + }, + 'AICODE03': { + 1: 'AICODE03-001', 2: 'AICODE03-002', + 3: 'AICODE03-003', 4: 'AICODE03-004', + 5: 'AICODE03-005', 6: 'AICODE03-006', + 7: 'AICODE03-007', 8: 'AICODE03-008', + 9: 'AICODE03-009', 10: 'AICODE03-010', + 11: 'AICODE03-011', 12: 'AICODE03-012', + }, + 'CREATE': { + 1: 'CREATE-001', 2: 'CREATE-002', 3: 'CREATE-003', + 4: 'CREATE-004', 5: 'CREATE-005', 6: 'CREATE-006', + 7: 'CREATE-007', 8: 'CREATE-008', 9: 'CREATE-009', + 10: 'CREATE-010', + }, + 'INVENT': { + 1: 'INVENT-001', 2: 'INVENT-002', 3: 'INVENT-003', + 4: 'INVENT-004', 5: 'INVENT-005', 6: 'INVENT-006', + 7: 'INVENT-007', 8: 'INVENT-008', 9: 'INVENT-009', + 10: 'INVENT-010', + }, +} + +# ============ 工具函数 ============ + +def calculate_week_number(target_date: date) -> int: + """计算给定日期是第几周""" + delta = target_date - SEMESTER_START_DATE + week_number = delta.days // 7 + 1 + return max(1, min(20, week_number)) + +def get_course_code_for_week(class_name: str, week_number: int) -> str: + """根据班级名称和周数获取课程代码""" + course_type = None + if 'AICODE03' in class_name: + course_type = 'AICODE03' + elif 'SPIKE' in class_name: + course_type = 'SPIKE' + elif 'CREATE' in class_name or 'Wedo' in class_name: + course_type = 'CREATE' + elif 'INVENT' in class_name or '发明世界' in class_name: + course_type = 'INVENT' + elif 'DISC' in class_name or '发现世界' in class_name or '小小班' in class_name or '小班' in class_name or '中班' in class_name: + course_type = 'DISC' + + if course_type and week_number in WEEK_TO_COURSE.get(course_type, {}): + return WEEK_TO_COURSE[course_type][week_number] + return f"{course_type}-{week_number:02d}" if course_type else f"UNKNOWN-{week_number:02d}" + +def find_all_classes() -> List[Path]: + """查找所有班级目录""" + classes = [] + if CLASS_DATA_PATH.exists(): + for item in CLASS_DATA_PATH.iterdir(): + if item.is_dir() and not item.name.startswith('.'): + classes.append(item) + return classes + +def find_student_profile(student_name: str) -> Optional[Tuple[Path, Path]]: + """ + 查找学生档案,返回(班级目录, 学生目录) + 如果找到多个档案,返回第一个 + """ + for class_dir in find_all_classes(): + # 先查找正式学生目录 + student_dir = class_dir / student_name + if student_dir.exists() and (student_dir / 'profile.md').exists(): + return (class_dir, student_dir) + + # 也检查一下补课目录(但补课目录一般不需要profile) + makeup_dir = class_dir / '补课' / student_name + if makeup_dir.exists(): + # 检查其他班级是否有这个学生的正式档案 + for other_class in find_all_classes(): + if other_class != class_dir: + other_student = other_class / student_name + if other_student.exists() and (other_student / 'profile.md').exists(): + return (other_class, other_student) + + return None + +def find_class_dir_by_name(class_name: str) -> Optional[Path]: + """根据班级名称查找班级目录""" + for class_dir in find_all_classes(): + if class_name in class_dir.name: + return class_dir + return None + +def get_date_str(date_obj: date = None) -> str: + """获取日期字符串(YYYYMMDD格式)""" + if date_obj is None: + date_obj = date.today() + return date_obj.strftime('%Y%m%d') + +def parse_date_str(date_str: str) -> date: + """解析日期字符串(YYYYMMDD格式)""" + return datetime.strptime(date_str, '%Y%m%d').date() + +# ============ 课评保存器类 ============ + +class EvaluationSaver: + def __init__(self, class_name: str, teaching_date: date = None): + self.class_name = class_name + self.teaching_date = teaching_date or date.today() + self.week_number = calculate_week_number(self.teaching_date) + self.date_str = get_date_str(self.teaching_date) + + # 查找班级目录 + self.class_dir = find_class_dir_by_name(class_name) + if not self.class_dir: + raise ValueError(f"找不到班级目录:{class_name}") + + self.course_code = get_course_code_for_week(self.class_dir.name, self.week_number) + + print(f"📅 授课日期:{self.teaching_date}") + print(f"📚 学期周数:第{self.week_number}周") + print(f"🎯 课程代码:{self.course_code}") + print(f"📁 班级目录:{self.class_dir.name}") + + def save_individual_evaluation( + self, + student_name: str, + evaluation_text: str, + is_makeup: bool = False, + original_class: Optional[str] = None, + course_topic: str = "", + ) -> Tuple[bool, List[Path]]: + """ + 保存单条学生课评 + + 参数: + student_name: 学生姓名 + evaluation_text: 课评内容 + is_makeup: 是否是补课学生 + original_class: 原班级名称(仅is_makeup=True时需要) + course_topic: 课程主题 + + 返回: + (是否成功, 保存的文件列表) + """ + saved_files = [] + + # 步骤1:查找学生档案位置 + profile_info = find_student_profile(student_name) + + # 步骤2:判断处理方式 + if is_makeup and original_class: + # 明确指定了是跨班级补课 + original_class_dir = find_class_dir_by_name(original_class) + if not original_class_dir: + print(f"⚠️ 找不到原班级目录:{original_class},尝试自动查找...") + profile_info = find_student_profile(student_name) + if profile_info: + original_class_dir = profile_info[0] + print(f"✅ 自动找到原班级:{original_class_dir.name}") + else: + print(f"❌ 无法确定原班级,只保存到补课班级侧") + original_class_dir = None + + success, files = self._save_makeup_evaluation( + student_name, evaluation_text, course_topic, original_class_dir + ) + return success, files + + elif is_makeup and profile_info: + # 标记为补课但档案在其他班级 → 跨班级补课 + original_class_dir, _ = profile_info + if original_class_dir.name != self.class_dir.name: + # 确实是跨班级 + print(f"🔄 检测到跨班级补课:学生档案在「{original_class_dir.name}」") + success, files = self._save_makeup_evaluation( + student_name, evaluation_text, course_topic, original_class_dir + ) + return success, files + else: + # 档案在当前班级 → 本班补课 + print(f"✅ 本班补课学生:{student_name}") + + # 标准保存方式(正式学生或补课但档案在当前班级) + # 确定学生目录 + student_dir = self.class_dir / student_name + if not student_dir.exists() or not (student_dir / 'profile.md').exists(): + if is_makeup: + # 补课但没有档案 → 使用补课目录 + student_dir = self.class_dir / '补课' / student_name + print(f"⚠️ 找不到正式档案,使用补课目录:{student_dir}") + else: + # 可能是新学生 + print(f"⚠️ 找不到学生档案:{student_name}") + create = input(f"是否为新学生创建档案?(y/n) ").lower() == 'y' + if create: + student_dir.mkdir(parents=True, exist_ok=True) + self._create_empty_profile(student_dir / 'profile.md', student_name) + else: + return False, [] + + # 创建feedback目录 + feedback_dir = student_dir / 'feedback' + feedback_dir.mkdir(parents=True, exist_ok=True) + + # 生成文件名 + eval_filename = f"{self.date_str}_{self.course_code}.md" + eval_filepath = feedback_dir / eval_filename + + # 格式化并保存课评 + formatted_eval = self._format_individual_evaluation( + student_name, evaluation_text, course_topic + ) + + eval_filepath.write_text(formatted_eval, encoding='utf-8') + saved_files.append(eval_filepath) + + print(f"✅ 已保存个人课评:{eval_filepath}") + + return True, saved_files + + def _save_makeup_evaluation( + self, + student_name: str, + evaluation_text: str, + course_topic: str, + original_class_dir: Optional[Path], + ) -> Tuple[bool, List[Path]]: + """ + 保存补课学生的双向记录 + + 规则: + 1. 补课班级侧:保存到「补课/{学生}/feedback/YYYYMMDD_课程编号.md」,内容开头注明来源 + 2. 原班级侧:保存到「{学生}/feedback/YYYYMMDD_课程编号-课次(补课-去班级名).md」,简单记录去向 + """ + saved_files = [] + + # 第一部分:补课班级侧记录 + makeup_student_dir = self.class_dir / '补课' / student_name + makeup_feedback_dir = makeup_student_dir / 'feedback' + makeup_feedback_dir.mkdir(parents=True, exist_ok=True) + + makeup_eval_filename = f"{self.date_str}_{self.course_code}.md" + makeup_eval_filepath = makeup_feedback_dir / makeup_eval_filename + + # 添加来源标注 + source_note = f"(补课,来自 {original_class_dir.name if original_class_dir else '其他班级'})" + full_eval_text = f"{source_note}\n\n{evaluation_text}" + + formatted_eval = self._format_individual_evaluation( + student_name, full_eval_text, course_topic + ) + + makeup_eval_filepath.write_text(formatted_eval, encoding='utf-8') + saved_files.append(makeup_eval_filepath) + print(f"✅ 已保存补课班级侧记录:{makeup_eval_filepath}") + + # 第二部分:原班级侧记录 + if original_class_dir: + original_student_dir = original_class_dir / student_name + if original_student_dir.exists(): + original_feedback_dir = original_student_dir / 'feedback' + original_feedback_dir.mkdir(parents=True, exist_ok=True) + + # 原班级侧文件名 + original_filename = f"{self.date_str}_{self.course_code}(补课-去{self.class_dir.name}).md" + original_filepath = original_feedback_dir / original_filename + + # 原班级侧只需要简单记录 + makeup_tracking_content = self._format_makeup_tracking( + student_name, self.class_dir.name + ) + + original_filepath.write_text(makeup_tracking_content, encoding='utf-8') + saved_files.append(original_filepath) + print(f"✅ 已保存原班级侧记录:{original_filepath}") + else: + print(f"⚠️ 找不到原班级学生目录,跳过原班级侧记录") + + return True, saved_files + + def _format_individual_evaluation( + self, + student_name: str, + evaluation_text: str, + course_topic: str = "", + ) -> str: + """格式化个人课评文件内容""" + lines = [] + + title = f"课程名称:{self.course_code}" + if course_topic: + title += f" {course_topic}" + + lines.append(f"# {title}") + lines.append("") + lines.append(f"**授课日期**:{self.teaching_date}") + lines.append("") + lines.append("**课评内容**:") + lines.append("") + lines.append(evaluation_text.strip()) + + return '\n'.join(lines) + + def _format_makeup_tracking(self, student_name: str, makeup_class_name: str) -> str: + """格式化补课追踪记录(原班级侧)""" + lines = [ + "# 补课记录", + "", + f"**日期**:{self.teaching_date}", + f"**课程**:{self.course_code}", + f"**学生**:{student_name}", + "**状态**:补课", + f"**去向班级**:{makeup_class_name}", + "**说明**:本节课程在{makeup_class_name}完成补课" + ] + return '\n'.join(lines) + + def _create_empty_profile(self, profile_path: Path, student_name: str): + """创建空的学生档案""" + content = f"""# 学生档案:{student_name} + +## 基础信息 +- 姓名:{student_name} +- 小名: +- 年龄: + +## 性格特点 +- 气质类型: +- 互动模式: +- 遇到困难时: + +## 学习特点 +- 学习方式偏好: +- 平均专注时长: +- 核心优势能力: + +## 家长沟通 +- 主要接送人: +- 期望沟通频率: +""" + profile_path.write_text(content, encoding='utf-8') + print(f"✅ 已创建学生档案:{profile_path}") + + +# ============ 交互式界面 ============ + +def interactive_mode(): + """交互式输入模式""" + print("="*60) + print("📚 穹狼乐高编程课评自动保存工具 v4.0") + print("="*60) + + # 选择班级 + print("\n可用班级:") + classes = find_all_classes() + for i, cls in enumerate(classes, 1): + print(f" {i}. {cls.name}") + + class_choice = input("\n请输入班级编号或班级名称:").strip() + if class_choice.isdigit(): + class_idx = int(class_choice) - 1 + if 0 <= class_idx < len(classes): + selected_class = classes[class_idx].name + else: + print("❌ 无效的班级编号") + return + else: + selected_class = class_choice + + # 输入日期 + date_input = input("\n请输入授课日期(YYYYMMDD,留空使用今天):").strip() + teaching_date = date.today() + if date_input: + teaching_date = parse_date_str(date_input) + + # 创建保存器 + try: + saver = EvaluationSaver(selected_class, teaching_date) + except ValueError as e: + print(f"❌ {e}") + return + + # 批量输入学生 + print("\n" + "="*60) + print("📝 开始输入学生表现(输入'q'结束)") + print("输入格式:学生姓名 课评内容 [补课]") + print("示例:小明 今天表现很好,搭建了很棒的作品!") + print("示例:小红 今天表现很稳定 补课") + print("="*60) + + all_saved_files = [] + + while True: + print() + line = input("请输入:").strip() + if not line: + continue + + if line.lower() == 'q': + break + + # 解析输入 + # 格式1:姓名 课评内容 标记 + parts = line.split(maxsplit=1) + if len(parts) < 2: + print("❌ 格式不正确:需要至少包含学生姓名和课评内容") + continue + + student_name = parts[0] + rest = parts[1] + + is_makeup = False + original_class = None + + # 检查是否有补课标记 + if '补课' in rest: + is_makeup = True + # 从文本中移除标记 + rest = rest.replace('补课', '').strip() + + # 询问课程主题 + course_topic = input(f"\n请输入{student_name}的课程主题(可选):").strip() + + # 保存 + print(f"\n正在保存 {student_name} 的课评...") + success, saved_files = saver.save_individual_evaluation( + student_name=student_name, + evaluation_text=rest, + is_makeup=is_makeup, + original_class=original_class, + course_topic=course_topic + ) + + if success: + all_saved_files.extend(saved_files) + print(f"✅ 保存成功!") + else: + print(f"❌ 保存失败") + + # 总结 + print("\n" + "="*60) + print(f"📊 全部完成!共保存 {len(all_saved_files)} 个文件") + for f in all_saved_files: + print(f" ✅ {f}") + print("="*60) + + +# ============ 主函数 ============ + +def main(): + parser = argparse.ArgumentParser(description='课评自动双轨保存工具') + parser.add_argument('-i', '--interactive', action='store_true', help='交互式输入模式') + parser.add_argument('--config', help='使用配置文件批量处理') + parser.add_argument('--class', help='班级名称') + parser.add_argument('--date', help='授课日期(YYYYMMDD)') + parser.add_argument('--student', help='学生姓名') + parser.add_argument('--text', help='课评内容文本文件路径') + parser.add_argument('--makeup', action='store_true', help='标记为补课学生') + parser.add_argument('--original-class', help='原班级名称(补课学生使用)') + parser.add_argument('--topic', help='课程主题') + + args = parser.parse_args() + + if args.interactive: + interactive_mode() + return + + if not getattr(args, 'class'): + print("❌ 请指定班级名称(--class)或使用交互式模式(-i)") + return + + if args.config: + print(f"📁 读取配置文件:{args.config}") + with open(args.config, 'r', encoding='utf-8') as f: + config = json.load(f) + + # 批量处理 + teaching_date = date.today() + if 'date' in config: + teaching_date = parse_date_str(config['date']) + + saver = EvaluationSaver(config['class'], teaching_date) + + for student_data in config.get('students', []): + print(f"\n正在处理:{student_data['name']}") + success, files = saver.save_individual_evaluation( + student_name=student_data['name'], + evaluation_text=student_data['text'], + is_makeup=student_data.get('makeup', False), + original_class=student_data.get('original_class'), + course_topic=student_data.get('topic', ''), + ) + if success: + print(f"✅ {student_data['name']} 保存成功") + return + + # 单条处理 + class_name = getattr(args, 'class') + + teaching_date = date.today() + if args.date: + teaching_date = parse_date_str(args.date) + + if not args.student: + print("❌ 请指定学生姓名(--student)") + return + + # 读取课评内容 + if args.text: + with open(args.text, 'r', encoding='utf-8') as f: + evaluation_text = f.read() + else: + print("❌ 请指定课评内容文件(--text)") + return + + saver = EvaluationSaver(class_name, teaching_date) + success, files = saver.save_individual_evaluation( + student_name=args.student, + evaluation_text=evaluation_text, + is_makeup=args.makeup, + original_class=args.original_class, + course_topic=args.topic or "", + ) + + if success: + print(f"✅ 保存成功!文件:{files}") + + +if __name__ == '__main__': + main() + diff --git a/src/fix_config.py b/src/fix_config.py index ad02504..7779c84 100644 --- a/src/fix_config.py +++ b/src/fix_config.py @@ -1,4 +1,5 @@ import json +import os data = { "skill_name": "keping-advanced", @@ -35,6 +36,12 @@ data = { "updated_at": "2026-05-09" } -with open(r"E:\classfeedback\.claude\skills\keping-advanced\config.json", "w", encoding="utf-8") as f: - json.dump(data, f, ensure_ascii=False, indent=2) -print("config.json updated successfully") +def main(): + base_dir = os.path.dirname(os.path.abspath(__file__)) + config_path = os.path.join(base_dir, '..', '.claude', 'skills', 'keping-advanced', 'config.json') + with open(config_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print("config.json updated successfully") + +if __name__ == '__main__': + main() diff --git a/src/fix_summary_names.py b/src/fix_summary_names.py new file mode 100644 index 0000000..c6b7485 --- /dev/null +++ b/src/fix_summary_names.py @@ -0,0 +1,196 @@ +import os +import re + +CLASS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.claude', 'memory', 'class') + +# Known student names per class (from profile.md files) +CLASS_STUDENTS = { + '发现世界-周四19点': ['梁昕乔', '钟昀昊', '林瀚丞'], + '发现世界-周六09点': ['余韫', '杨佳兴', '林嘉铭', '胡翰铭'], + '发现世界-周六19点': ['赖韵恬'], + 'AICODE03小Q周五1900': ['沙佩琪', '李怡瞳', '黄榆斐', '谢善诺'], + 'AICODE03小Q周六1400': ['黄俊博', '陈昕柔', '李汶浩', '曾乐凯'], + 'SPIKE02-周日1030': ['洪一栩', '王骏诚', '吴浩洋', '吴浩骏', '邓琬颖', '邓琬曦', '方柳莫'], + 'Wedo创造世界-周六1030': ['黄馨宸', '黄晓瑜', '罗钧龄', '简思霖', '梁家铭', '简思瑜'], + 'Wedo创造世界-周六16点': ['马悦然', '冯彦哲'], + '发现世界-周日下午16点': [], + '发明世界-周日14点': [], + '周日9点': [], +} + +def load_student_nicknames(): + nicknames = {} + for root, dirs, files in os.walk(CLASS_DIR): + for f in files: + if f == 'profile.md': + file_path = os.path.join(root, f) + parts = os.path.normpath(file_path).split(os.sep) + class_name = '' + student_name = '' + for i, p in enumerate(parts): + if p == 'profile.md' and i >= 2: + student_name = parts[i-1] + class_name = parts[i-2] + break + + with open(file_path, 'r', encoding='utf-8') as pf: + text = pf.read() + # Try to find nickname + nm = re.search(r'\*\*小名/昵称\*\*\s*\|\s*(\S+)', text) + if nm: + nick = nm.group(1).strip() + if student_name not in nicknames: + nicknames[student_name] = [] + nicknames[student_name].append(nick) + nicknames[nick] = student_name + return nicknames + +STUDENT_NICKNAMES = {} + +def find_student_for_nickname(nick, class_name): + """Match a truncated/nickname to full student name for a class""" + students = CLASS_STUDENTS.get(class_name, []) + + # Direct match + if nick in students: + return nick + + # Match by substring (handles truncated names) + for student in students: + if nick in student or student.startswith(nick): + return student + + # Match by nickname + if STUDENT_NICKNAMES: + for s in students: + nicks = STUDENT_NICKNAMES.get(s, []) + for n in nicks: + if nick in n or n in nick: + return s + + return nick + +def fix_names_in_file(file_path): + with open(file_path, 'r', encoding='utf-8') as f: + text = f.read() + + parts = os.path.normpath(file_path).split(os.sep) + class_name = '' + for i, p in enumerate(parts): + if p == 'summaries' and i >= 1: + class_name = parts[i-1] + break + + if class_name not in CLASS_STUDENTS: + return False + + students = CLASS_STUDENTS[class_name] + if not students: + return False + + lines = text.split('\n') + changed = False + + # Track names found in the file + names_in_table = [] + names_in_sections = [] + + # First pass: find all nicknames used + for line in lines: + stripped = line.strip() + # Check table rows + if stripped.startswith('|') and not stripped.startswith('|:') and not stripped.startswith('|---'): + cells = [c.strip() for c in stripped.split('|') if c.strip()] + if cells and len(cells) >= 2: + cell = cells[0] + # Skip header-like cells + if cell not in ['学生', '状态', '类型', '档案位置', '操作'] and cell not in ['序号']: + names_in_table.append(cell) + + # Check section headers + m = re.match(r'^###\s+(.+?)(?:\s*[-—]|\s*$)', stripped) + if m: + name = m.group(1).strip() + # Remove numbering and emoji + name = re.sub(r'^\d+[.、]\s*', '', name) + name = re.sub(r'\s*☑.*', '', name) + name = re.sub(r'\[.*?\]', '', name) + name = name.strip() + if name and len(name) < 10: + names_in_sections.append(name) + + if not names_in_table and not names_in_sections: + return False + + # Build mapping from truncated/nickname to full name + mapping = {} + for nick in set(names_in_table + names_in_sections): + full = find_student_for_nickname(nick, class_name) + if full != nick: + mapping[nick] = full + + if not mapping: + return False + + # Apply mapping to file + new_lines = [] + for line in lines: + stripped = line.strip() + new_line = line + + # Fix table rows + if stripped.startswith('|') and not stripped.startswith('|:') and not stripped.startswith('|---'): + for nick, full in mapping.items(): + # Escape special regex characters in nick + escaped_nick = re.escape(nick) + if re.search(escaped_nick, new_line): + new_line = re.sub(r'(?模板文件未找到" + + class_name = params.get("class", ["未知班级"])[0] + week = params.get("week", ["1"])[0] + course_code = params.get("course", ["UNKNOWN-001"])[0] + course_theme = params.get("theme", ["未知主题"])[0] + course_knowledge = params.get("knowledge", [""])[0] + date_str = params.get("date", ["2026-01-01"])[0] + + # 读取班级学生 + regular_students, makeup_students = get_class_students(class_name) + + # 构建学生数据 JS + students_js = [] + for s in regular_students: + profile = get_student_profile(class_name, s["name"]) + students_js.append({ + "name": s["name"], + "status": "出勤", + "performance": "", + "profile": profile + }) + + # 补课学生作为可选列表 + makeup_names = [m["name"] for m in makeup_students] + + # 课程信息 + course_info = { + "code": course_code, + "title": course_theme, + "knowledge": course_knowledge.split(",") if course_knowledge else ["暂无"], + "duration": "60分钟" + } + + # 注入数据:替换模板中的占位配置 + html = template + + # 替换初始班级/周数/日期信息 + html = html.replace('"发现世界-周四19点"', f'"{class_name}"') + html = html.replace('"第11周 | 2026-05-16"', f'"第{week}周 | {date_str}"') + html = html.replace('currentWeek = 11', f'currentWeek = {week}') + html = html.replace('"2026-05-16"', f'"{date_str}"') + html = html.replace('"DISC-011"', f'"{course_code}"') + html = html.replace('"蜥蜴"', f'"{course_theme}"') + html = html.replace( + '["关节连接","可动结构","仿生设计"]', + json.dumps(course_info["knowledge"], ensure_ascii=False) + ) + html = html.replace('"📚 课程目标:DISC-011 蜥蜴"', + f'"📚 课程目标:{course_code} {course_theme}"') + + # 替换学生模板数据 + old_students_json = json.dumps([ + {"name": "梁家铭", "status": "出勤", "performance": ""}, + {"name": "简思瑜", "status": "出勤", "performance": ""}, + {"name": "简思霖", "status": "请假", "performance": ""}, + {"name": "罗钧龄", "status": "出勤", "performance": ""}, + {"name": "黄晓瑜", "status": "出勤", "performance": ""}, + {"name": "黄馨宸", "status": "请假", "performance": ""} + ], ensure_ascii=False) + + new_students_json = json.dumps(students_js, ensure_ascii=False) + html = html.replace(old_students_json, new_students_json) + + # 注入补课学生可选项 + html = html.replace( + "", + f""" +const makeupStudents = {json.dumps(makeup_names, ensure_ascii=False)}; +const classDir = "{class_name}"; +""" + ) + + return html + + +class FormHandler(http.server.BaseHTTPRequestHandler): + def log_message(self, format, *args): + """静默日志""" + pass + + def do_GET(self): + parsed = urllib.parse.urlparse(self.path) + + if parsed.path == "/" or parsed.path == "/form": + params = urllib.parse.parse_qs(parsed.query) + html = build_form_html(params) + self.send_response(200) + self.send_header("Content-Type", "text/html; charset=utf-8") + self.send_header("Access-Control-Allow-Origin", "*") + self.end_headers() + self.wfile.write(html.encode("utf-8")) + else: + self.send_response(404) + self.end_headers() + + def do_POST(self): + if self.path == "/api/submit": + content_length = int(self.headers.get("Content-Length", 0)) + body = self.rfile.read(content_length) + data = json.loads(body) + + # 保存到临时目录 + TMP_DIR.mkdir(parents=True, exist_ok=True) + class_name = data.get("class", "unknown") + safe_name = re.sub(r'[<>:"/\\|?*]', '_', class_name) + output_file = TMP_DIR / f"evaluation_input_{safe_name}.json" + + with open(output_file, "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) + + # 同时写一个信号文件通知 AI + signal_file = TMP_DIR / "EVALUATION_READY.txt" + signal_file.write_text( + f"班级: {class_name}\n" + f"提交时间: {data.get('date', '')}\n" + f"数据文件: {output_file}\n", + encoding="utf-8" + ) + + resp = { + "success": True, + "message": f"已保存!班级:{class_name},共 {len(data.get('students', []))} 人", + "file": str(output_file) + } + + self.send_response(200) + self.send_header("Content-Type", "application/json; charset=utf-8") + self.send_header("Access-Control-Allow-Origin", "*") + self.end_headers() + self.wfile.write(json.dumps(resp, ensure_ascii=False).encode("utf-8")) + else: + self.send_response(404) + self.end_headers() + + def do_OPTIONS(self): + """CORS preflight""" + self.send_response(200) + self.send_header("Access-Control-Allow-Origin", "*") + self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + self.send_header("Access-Control-Allow-Headers", "Content-Type") + self.end_headers() + + +def main(): + print(f"🚀 课评表单服务器启动中...") + print(f" 端口: {PORT}") + print(f" 临时目录: {TMP_DIR}") + + # 确保临时目录存在 + TMP_DIR.mkdir(parents=True, exist_ok=True) + + server = http.server.HTTPServer(("127.0.0.1", PORT), FormHandler) + print(f"✅ 服务器已启动: http://localhost:{PORT}/form") + print(f" 按 Ctrl+C 停止服务器") + + try: + server.serve_forever() + except KeyboardInterrupt: + print("\n🛑 服务器已停止") + server.server_close() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/test_class_summaries.py b/src/test_class_summaries.py new file mode 100644 index 0000000..ee238d2 --- /dev/null +++ b/src/test_class_summaries.py @@ -0,0 +1,38 @@ +import sys +sys.path.insert(0, 'src') +sys.stdout.reconfigure(encoding='utf-8') + +from unify_class_summaries import * + +# Test 1: V2 format (old) +file_path = r'.claude\memory\class\发现世界-周四19点\summaries\20260417_DISC-007_班级反馈.md' +print('=== 测试V2旧格式 ===') +file_info = extract_file_info(file_path) +print(f'文件信息: {file_info}') + +with open(file_path, 'r', encoding='utf-8') as f: + text = f.read() +fmt = detect_format(text) +print(f'检测格式: {fmt}') +print(f'周数: {extract_week(text)}') +print(f'主题: {extract_theme(text)}') + +feedbacks = extract_v2_feedbacks(text) +print(f'学生课评数: {len(feedbacks)}') +for fb in feedbacks: + print(f' - {fb["name"]}: {fb["content"][:50]}...') + +overall = extract_overall(text) +print(f'整体情况(前100字): {overall[:100]}') + +new_text = v2_to_v1(text, file_info) +print('\n新格式预览(前40行):') +for line in new_text.split('\n')[:40]: + print(line) + +print('\n\n=== 测试V1最新格式(应跳过) ===') +file_path2 = r'.claude\memory\class\发现世界-周四19点\summaries\20260514_DISC-011_班级反馈.md' +with open(file_path2, 'r', encoding='utf-8') as f: + text2 = f.read() +print(f'格式: {detect_format(text2)}') +print(f'应跳过: {is_new_format(text2)}') \ No newline at end of file diff --git a/src/test_profiles.py b/src/test_profiles.py new file mode 100644 index 0000000..7bbd0c5 --- /dev/null +++ b/src/test_profiles.py @@ -0,0 +1,41 @@ +import sys +sys.path.insert(0, 'src') +sys.stdout.reconfigure(encoding='utf-8') + +from unify_profiles import * + +# Test 1: Old list format (余韫) +file_path = r'.claude\memory\class\发现世界-周六09点\余韫\profile.md' +print('=== 测试1: 旧版列表格式 ===') +with open(file_path, 'r', encoding='utf-8') as f: + text = f.read() +fmt = detect_format(text) +print(f'检测格式: {fmt}') +data = parse_old_list_format(text, file_path) +print(f'姓名: {data["name"]}') +print(f'昵称: {data["nickname"]}') +print(f'气质: {data["temperament"]}') +print(f'优势: {data["strengths"]}') +print(f'弱点: {data["weaknesses"]}') +print(f'教学建议数: {len(data["teaching_tips"])}') +print(f'成长记录数: {len(data["growth_records"])}') +new_text = generate_new_profile(data, file_path) +print('新格式预览(前30行):') +for line in new_text.split('\n')[:30]: + print(line) + +print('\n\n=== 测试2: 新结构但标题错误 ===') +file_path2 = r'.claude\memory\class\发现世界-周六09点\胡翰铭\profile.md' +with open(file_path2, 'r', encoding='utf-8') as f: + text2 = f.read() +fmt2 = detect_format(text2) +print(f'检测格式: {fmt2}') +new_text2 = fix_wrong_title(text2, file_path2) +print('新标题:', new_text2.split('\n')[0]) + +print('\n=== 测试3: 独特格式(赖韵恬) ===') +file_path3 = r'.claude\memory\class\发现世界-周六19点\赖韵恬\profile.md' +with open(file_path3, 'r', encoding='utf-8') as f: + text3 = f.read() +fmt3 = detect_format(text3) +print(f'检测格式: {fmt3}') \ No newline at end of file diff --git a/src/test_unify.py b/src/test_unify.py new file mode 100644 index 0000000..3373b48 --- /dev/null +++ b/src/test_unify.py @@ -0,0 +1,30 @@ +import sys +sys.path.insert(0, 'src') +sys.stdout.reconfigure(encoding='utf-8') + +from unify_feedback import * + +file_path = r'.claude\memory\class\发现世界-周四19点\梁昕乔\feedback\20260514_DISC-011.md' +file_info = extract_file_info(file_path) +print('文件信息:', file_info) +print('---') + +with open(file_path, 'r', encoding='utf-8') as f: + text = f.read() +print('原始内容前200字:') +print(text[:200]) +print('...') + +parsed = parse_feedback_content(text, file_info) +print('解析结果:') +for k, v in parsed.items(): + if isinstance(v, list): + print(f' {k}: {v}') + else: + display = v[:100] if len(v) > 100 else v + print(f' {k}: {display}') + +print('---') +new_text = format_feedback(file_info, parsed) +print('新格式:') +print(new_text) \ No newline at end of file diff --git a/src/unify_class_summaries.py b/src/unify_class_summaries.py new file mode 100644 index 0000000..352fa59 --- /dev/null +++ b/src/unify_class_summaries.py @@ -0,0 +1,378 @@ +import os +import re + +CLASS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.claude', 'memory', 'class') + +def extract_file_info(file_path): + parts = os.path.normpath(file_path).split(os.sep) + filename = os.path.basename(file_path) + + class_name = '' + for i, p in enumerate(parts): + if p == 'summaries' and i >= 1: + class_name = parts[i-1] + break + + date_match = re.match(r'(\d{4})(\d{2})(\d{2})_', filename) + date_str = '' + if date_match: + date_str = f'{date_match.group(1)}-{date_match.group(2)}-{date_match.group(3)}' + + course_match = re.search(r'(AICODE03|SPIKE|DISC|CREATE|MECH|TUBE|INVENT|WEDO)-(\d+)', filename) + course_code = '' + if course_match: + prefix = course_match.group(1) + if prefix == 'WEDO': + prefix = 'CREATE' + num = course_match.group(2).zfill(3) + course_code = f'{prefix}-{num}' + + return { + 'class_name': class_name, + 'date': date_str, + 'course_code': course_code, + 'filename': filename, + } + +def is_new_format(text): + return '## 本周课评状态' in text and '## 本周班级整体情况' in text + +def is_v2_format(text): + return '## 本周概览' in text + +def is_v3_format(text): + return '课评状态面板' in text or '## 📊' in text + +def detect_format(text): + if is_new_format(text): + return 'v1' + if is_v2_format(text): + return 'v2' + if is_v3_format(text): + return 'v3' + return 'unknown' + +def extract_week(text): + m = re.search(r'第(\d+)周', text) + return m.group(1) if m else '' + +def extract_theme(text): + lines = text.split('\n') + for line in lines: + if '课程主题' in line: + m = re.search(r'[::]\s*(.*)', line) + if m: + return m.group(1).strip() + return '' + +def extract_name_from_header(text): + text = re.sub(r'\s*[((][^))]*[))]', '', text) + text = re.sub(r'\s*[-—]\s*.*', '', text) + text = re.sub(r'^\d+[.、]\s*', '', text) + text = re.sub(r'\s*☑.*', '', text) + text = re.sub(r'\[.*?\]', '', text) + return text.strip() + +def extract_student_feedbacks(text): + feedbacks = [] + lines = text.split('\n') + i = 0 + current_student = {} + content = [] + in_feedback = False + + while i < len(lines): + line = lines[i] + stripped = line.strip() + + if any(stripped.startswith(p) for p in ['## 班级整体观察', '## 本周班级整体情况', '## 教师周记', '## 数据统计', '## 本周概览', '## 详细课评']): + if current_student and current_student.get('name'): + current_student['content'] = '\n'.join(content).strip() + feedbacks.append(current_student) + current_student = {} + content = [] + in_feedback = False + + if re.match(r'^###\s+\S', stripped) and '### 课程信息' not in stripped and '### 学生表现' not in stripped and '### 快速统计' not in stripped and '### 学生状态' not in stripped and '### 课程目标' not in stripped: + if current_student and current_student.get('name'): + current_student['content'] = '\n'.join(content).strip() + feedbacks.append(current_student) + + full_line = stripped + student_name = extract_name_from_header(full_line) + if student_name: + current_student = {'name': student_name} + content = [] + in_feedback = True + i += 1 + continue + + if in_feedback: + content.append(line) + + i += 1 + + if current_student and current_student.get('name'): + current_student['content'] = '\n'.join(content).strip() + feedbacks.append(current_student) + + return feedbacks + +def extract_v2_feedbacks(text): + feedbacks = [] + lines = text.split('\n') + i = 0 + current_student = None + content = [] + in_detail = False + + while i < len(lines): + line = lines[i] + stripped = line.strip() + + if stripped.startswith('## 班级整体观察') or stripped.startswith('## 教师周记') or stripped.startswith('## 数据统计') or stripped.startswith('## 本周班级整体情况'): + if current_student: + current_student['content'] = '\n'.join(content).strip() + feedbacks.append(current_student) + current_student = None + content = [] + in_detail = False + + if stripped == '## 详细课评': + in_detail = True + i += 1 + continue + + if in_detail and re.match(r'^###\s+\S', stripped): + if current_student: + current_student['content'] = '\n'.join(content).strip() + feedbacks.append(current_student) + + full_line = stripped[4:] + student_name = extract_name_from_header(full_line) + if student_name: + current_student = {'name': student_name} + content = [] + i += 1 + continue + + if in_detail and current_student: + content.append(line) + + i += 1 + + if current_student: + current_student['content'] = '\n'.join(content).strip() + feedbacks.append(current_student) + + return feedbacks + +def extract_overall(text): + overall_lines = [] + lines = text.split('\n') + in_overall = False + capturing = False + + for line in lines: + stripped = line.strip() + if stripped == '## 班级整体观察' or stripped == '## 本周班级整体情况': + in_overall = True + capturing = True + continue + if stripped in ['## 教师周记', '## 数据统计', '## 详细课评', '## 本周概览', '## 本周课评状态']: + capturing = False + continue + if in_overall and capturing: + overall_lines.append(line) + + return '\n'.join(overall_lines).strip() + +def v2_to_v1(text, file_info): + week = extract_week(text) + theme = extract_theme(text) + feedbacks = extract_v2_feedbacks(text) + overall = extract_overall(text) + + lines = [] + lines.append(f'# {file_info["class_name"]} 第{week}周汇总') + lines.append('') + lines.append(f'> 课程代码:{file_info["course_code"]}') + if theme: + lines.append(f'> 课程主题:{theme}') + lines.append(f'> 上课日期:{file_info["date"]}') + lines.append(f'> 班级人数:待确认') + lines.append('') + lines.append('---') + lines.append('') + lines.append('## 本周课评状态') + lines.append('') + lines.append('| 学生 | 状态 | 类型 | 档案位置 | 操作 |') + lines.append('|:-----|:----:|:----:|:---------|:----:|') + for fb in feedbacks: + lines.append(f'| {fb["name"]} | ✅ 已保存 | 常规学生 | 本班 | [查看] |') + lines.append('') + lines.append('---') + lines.append('') + lines.append('## 学生课评列表') + lines.append('') + for fb in feedbacks: + lines.append(f'### {fb["name"]} - 常规学生 ✅') + lines.append('') + if fb.get('content'): + lines.append(fb['content']) + lines.append('') + lines.append('**教师备注**:') + lines.append('- 状态:已保存') + lines.append('- 个人档案:已同步') + lines.append('- 亮点:待补充') + lines.append('') + lines.append('---') + lines.append('') + + lines.append('## 本周班级整体情况') + lines.append('') + if overall: + lines.append(overall) + else: + lines.append('### 课程目标达成度') + lines.append('- **知识点掌握**:待补充') + lines.append('- **技能操作**:待补充') + lines.append('') + lines.append('### 共性亮点') + lines.append('1. ') + lines.append('') + lines.append('### 共性问题') + lines.append('1. 无明显共性问题') + + lines.append('') + lines.append('---') + lines.append('') + lines.append(f'*生成时间:{file_info["date"]}*') + + return '\n'.join(lines) + +def v3_to_v1(text, file_info): + week = extract_week(text) + theme = extract_theme(text) + feedbacks = extract_student_feedbacks(text) + overall = extract_overall(text) + + lines = [] + lines.append(f'# {file_info["class_name"]} 第{week}周汇总') + lines.append('') + lines.append(f'> 课程代码:{file_info["course_code"]}') + if theme: + lines.append(f'> 课程主题:{theme}') + lines.append(f'> 上课日期:{file_info["date"]}') + lines.append(f'> 班级人数:待确认') + lines.append('') + lines.append('---') + lines.append('') + lines.append('## 本周课评状态') + lines.append('') + lines.append('| 学生 | 状态 | 类型 | 档案位置 | 操作 |') + lines.append('|:-----|:----:|:----:|:---------|:----:|') + for fb in feedbacks: + lines.append(f'| {fb["name"]} | ✅ 已保存 | 常规学生 | 本班 | [查看] |') + lines.append('') + lines.append('---') + lines.append('') + lines.append('## 学生课评列表') + lines.append('') + for fb in feedbacks: + lines.append(f'### {fb["name"]} - 常规学生 ✅') + lines.append('') + if fb.get('content'): + lines.append(fb['content']) + lines.append('') + lines.append('**教师备注**:') + lines.append('- 状态:已保存') + lines.append('- 个人档案:已同步') + lines.append('- 亮点:待补充') + lines.append('') + lines.append('---') + lines.append('') + + lines.append('## 本周班级整体情况') + lines.append('') + if overall: + lines.append(overall) + else: + lines.append('### 课程目标达成度') + lines.append('- **知识点掌握**:待补充') + lines.append('- **技能操作**:待补充') + lines.append('') + lines.append('### 共性亮点') + lines.append('1. ') + lines.append('') + lines.append('### 共性问题') + lines.append('1. 无明显共性问题') + + lines.append('') + lines.append('---') + lines.append('') + lines.append(f'*生成时间:{file_info["date"]}*') + + return '\n'.join(lines) + +def process_summary(file_path, force=False): + with open(file_path, 'r', encoding='utf-8') as f: + text = f.read() + + file_info = extract_file_info(file_path) + fmt = detect_format(text) + + if fmt == 'v1' and not force: + return False + + if fmt == 'v1' and force: + pass + elif fmt == 'v2': + pass + elif fmt == 'v3': + pass + else: + return False + + new_text = v2_to_v1(text, file_info) if fmt in ['v1', 'v2'] else v3_to_v1(text, file_info) + + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_text) + return True + +def main(): + import sys + force = '--force' in sys.argv + + updated = 0 + skipped = 0 + errors = 0 + + for root, dirs, files in os.walk(CLASS_DIR): + if 'summaries' not in root.split(os.sep): + continue + + for f in files: + if not f.endswith('.md'): + continue + file_path = os.path.join(root, f) + try: + if process_summary(file_path): + updated += 1 + rel = os.path.relpath(file_path, CLASS_DIR) + print(f' ✅ 已更新: {rel}') + else: + skipped += 1 + except Exception as e: + errors += 1 + rel = os.path.relpath(file_path, CLASS_DIR) + print(f' ❌ 错误: {rel} - {e}') + + print(f'\n{"="*50}') + print(f'更新完成!') + print(f' ✅ 已更新: {updated} 个文件') + print(f' ⏭️ 已跳过(已是最新格式): {skipped} 个文件') + print(f' ❌ 错误: {errors} 个文件') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/src/unify_feedback.py b/src/unify_feedback.py new file mode 100644 index 0000000..348032e --- /dev/null +++ b/src/unify_feedback.py @@ -0,0 +1,346 @@ +import os +import re + +CLASS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.claude', 'memory', 'class') + +COURSE_TYPE_MAP = { + 'AICODE03': 'AICODE03(AICODE03平台)', + 'SPIKE': 'SPIKE(PRIME套装)', + 'DISC': 'DISC(螺丝刀套装45002)', + 'CREATE': 'CREATE(WEDO)', + 'MECH': 'MECH(9686动力机械)', + 'TUBE': 'TUBE(管道游戏套装)', + 'INVENT': 'INVENT(智能笔套装)', + 'WEDO': 'CREATE(WEDO)', +} + +def extract_file_info(file_path): + filename = os.path.basename(file_path) + parts = os.path.normpath(file_path).split(os.sep) + + class_name = None + student_name = None + for i, part in enumerate(parts): + if part == 'feedback': + if i >= 2: + student_name = parts[i-1] + class_name = parts[i-2] + break + + date_match = re.match(r'(\d{4})(\d{2})(\d{2})_', filename) + date_str = '' + if date_match: + date_str = f'{date_match.group(1)}-{date_match.group(2)}-{date_match.group(3)}' + + course_match = re.search(r'(AICODE03|SPIKE|DISC|CREATE|MECH|TUBE|INVENT|WEDO)-(\d+)', filename) + course_code = '' + if course_match: + prefix = course_match.group(1) + if prefix == 'WEDO': + prefix = 'CREATE' + num = course_match.group(2).zfill(3) + course_code = f'{prefix}-{num}' + + course_type = '' + for prefix in ['AICODE03', 'SPIKE', 'DISC', 'CREATE', 'MECH', 'TUBE', 'INVENT']: + if course_code.startswith(prefix): + course_type = COURSE_TYPE_MAP.get(prefix, prefix) + break + + return { + 'class_name': class_name or '', + 'student_name': student_name or '', + 'date': date_str, + 'course_code': course_code, + 'course_type': course_type, + 'filename': filename, + } + +def parse_feedback_content(text, file_info): + result = { + 'theme': '', + 'content': '', + 'assessments': [], + 'highlights': '', + 'concerns': '', + 'confirmed': '', + 'core_performance': '', + } + + lines = text.split('\n') + content_lines = [] + in_content = False + in_assessment = False + in_teacher_notes = False + in_theme = False + + i = 0 + while i < len(lines): + line = lines[i] + stripped = line.strip() + + if re.match(r'^#\s+\d{4}-\d{2}-\d{2}\s*\|\s*', stripped): + parts = re.split(r'\s*\|\s*', stripped) + if len(parts) >= 3: + result['theme'] = parts[2].strip() + elif len(parts) >= 2: + result['theme'] = parts[1].strip() + i += 1 + continue + + if re.match(r'^#\s+课程主题[::]', stripped): + result['theme'] = stripped.split(':', 1)[-1].strip() if ':' in stripped else stripped.split(':', 1)[-1].strip() + i += 1 + continue + + theme_match = re.match(r'^\*\*课程主题\*\*[::]?\s*(.*)', stripped) + if theme_match: + result['theme'] = theme_match.group(1).strip() + i += 1 + continue + + core_match = re.match(r'^\*\*核心表现\*\*[::]?\s*(.*)', stripped) + if core_match: + result['core_performance'] = core_match.group(1).strip() + i += 1 + continue + + if re.match(r'^##\s*课评内容', stripped): + in_content = True + i += 1 + continue + + if re.match(r'^\*\*课评内容\*\*', stripped): + in_content = True + i += 1 + continue + + if re.match(r'^\*\*能力评估\*\*', stripped): + in_content = False + in_assessment = True + i += 1 + continue + + if re.match(r'^\*\*教师备注\*\*', stripped): + in_content = False + in_assessment = False + in_teacher_notes = True + i += 1 + continue + + if re.match(r'^-{3,}\s*$', stripped) and not in_content: + in_teacher_notes = False + i += 1 + continue + + if in_assessment: + assess_match = re.match(r'^-\s*(.+?)[::]\s*(.+)', stripped) + if assess_match: + result['assessments'].append(f"- {assess_match.group(1).strip()}:{assess_match.group(2).strip()}") + i += 1 + continue + + if in_teacher_notes: + note_match = re.match(r'^-\s*亮点[::]\s*(.*)', stripped) + if note_match: + result['highlights'] = note_match.group(1).strip() + i += 1 + continue + + note_match = re.match(r'^-\s*需关注[::]\s*(.*)', stripped) + if note_match: + result['concerns'] = note_match.group(1).strip() + i += 1 + continue + + note_match = re.match(r'^-\s*与档案对应[::]\s*(.*)', stripped) + if note_match: + if not result['highlights']: + result['highlights'] = note_match.group(1).strip() + i += 1 + continue + + note_match = re.match(r'^-\s*确认状态[::]\s*(.*)', stripped) + if note_match: + result['confirmed'] = note_match.group(1).strip() + i += 1 + continue + + note_match = re.match(r'^-\s*(.+?)[::]\s*(.*)', stripped) + if note_match: + key = note_match.group(1).strip() + val = note_match.group(2).strip() + if '亮点' in key or 'highlight' in key.lower(): + result['highlights'] = val + elif '关注' in key or 'concern' in key.lower(): + result['concerns'] = val + elif '确认' in key or 'confirm' in key.lower(): + result['confirmed'] = val + i += 1 + continue + + if in_content: + if re.match(r'^-{3,}\s*$', stripped): + in_content = False + i += 1 + continue + if re.match(r'^\*\*.*\*\*', stripped): + in_content = False + i += 1 + continue + if re.match(r'^#', stripped): + in_content = False + i += 1 + continue + if re.match(r'^\*学生[::].*', stripped): + in_content = False + i += 1 + continue + if re.match(r'^\*生成日期[::].*', stripped): + in_content = False + i += 1 + continue + if re.match(r'^\*记录开始日期[::].*', stripped): + in_content = False + i += 1 + continue + content_lines.append(line) + i += 1 + continue + + if not in_content and not in_assessment and not in_teacher_notes: + if stripped and not re.match(r'^(#|---|\*\*.*\*\*|\*.*\*|$)', stripped): + if not re.match(r'^\*\*(日期|授课日期)\*\*', stripped): + if not re.match(r'^#\s+\d{4}-\d{2}-\d{2}', stripped): + content_lines.append(line) + + i += 1 + + result['content'] = '\n'.join(content_lines).strip() + + if not result['confirmed'] and file_info['date']: + result['confirmed'] = f'☑ 已确认({file_info["date"]})' + + return result + +def format_feedback(file_info, parsed): + course_prefix = file_info['course_code'].split('-')[0] if file_info['course_code'] else '' + + lines = [] + lines.append(f'# {file_info["course_code"]} 课评') + lines.append('') + lines.append(f'**日期**: {file_info["date"]}') + + if parsed['theme']: + lines.append(f'**课程主题**:{parsed["theme"]}') + + if parsed['core_performance']: + lines.append(f'**核心表现**:{parsed["core_performance"]}') + + lines.append('') + lines.append('**课评内容**:') + lines.append('') + + if parsed['content']: + lines.append(parsed['content']) + + if parsed['assessments']: + lines.append('') + lines.append('**能力评估**:') + for a in parsed['assessments']: + lines.append(a) + + lines.append('') + lines.append('**教师备注**:') + lines.append(f'- 亮点:{parsed["highlights"]}') + lines.append(f'- 需关注:{parsed["concerns"]}') + lines.append(f'- 确认状态:{parsed["confirmed"]}') + + lines.append('') + lines.append('---') + lines.append('') + lines.append('---') + + student_display = file_info['student_name'] + lines.append(f'*学生:{student_display} | 课程:{file_info["course_type"]}*') + lines.append('*记录开始日期:2026-03-25*') + + return '\n'.join(lines) + +def is_already_target_format(text, file_info): + lines = text.strip().split('\n') + if not lines: + return False + + first_line = lines[0].strip() + expected_title = f'# {file_info["course_code"]} 课评' + if first_line != expected_title: + return False + + has_date = False + has_content = False + has_teacher_notes = False + has_footer = False + + for line in lines: + stripped = line.strip() + if re.match(r'^\*\*日期\*\*', stripped): + has_date = True + if re.match(r'^\*\*课评内容\*\*', stripped): + has_content = True + if re.match(r'^\*\*教师备注\*\*', stripped): + has_teacher_notes = True + if re.match(r'^\*学生[::].*\|.*课程[::]', stripped): + has_footer = True + + return has_date and has_content and has_teacher_notes and has_footer + +def process_feedback_file(file_path): + file_info = extract_file_info(file_path) + + with open(file_path, 'r', encoding='utf-8') as f: + text = f.read() + + if is_already_target_format(text, file_info): + return False + + parsed = parse_feedback_content(text, file_info) + new_text = format_feedback(file_info, parsed) + + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_text) + + return True + +def main(): + updated_count = 0 + skipped_count = 0 + error_count = 0 + + for root, dirs, files in os.walk(CLASS_DIR): + if 'feedback' not in root.split(os.sep): + continue + + for f in files: + if not f.endswith('.md'): + continue + + file_path = os.path.join(root, f) + try: + if process_feedback_file(file_path): + updated_count += 1 + print(f' ✅ 已更新: {os.path.relpath(file_path, CLASS_DIR)}') + else: + skipped_count += 1 + except Exception as e: + error_count += 1 + print(f' ❌ 错误: {os.path.relpath(file_path, CLASS_DIR)} - {e}') + + print(f'\n{"="*50}') + print(f'更新完成!') + print(f' ✅ 已更新: {updated_count} 个文件') + print(f' ⏭️ 已跳过(已是最新格式): {skipped_count} 个文件') + print(f' ❌ 错误: {error_count} 个文件') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/src/unify_profiles.py b/src/unify_profiles.py new file mode 100644 index 0000000..dee6d9d --- /dev/null +++ b/src/unify_profiles.py @@ -0,0 +1,641 @@ +import os +import re + +CLASS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.claude', 'memory', 'class') + +def detect_format(text): + first_line = text.strip().split('\n')[0].strip() + if first_line.startswith('# 学生画像档案'): + return 'new' + if first_line.startswith('# 用户画像'): + if '|' in text[:500]: + return 'new_structure_wrong_title' + else: + return 'old_list' + if '用户画像' in first_line: + return 'unique' + return 'unknown' + +def parse_old_list_format(text, file_path): + data = { + 'name': '', 'nickname': '', 'gender': '', 'class_name': '', 'class_time': '', + 'campus': '', 'course_type': '', 'enroll_date': '', 'birthday': '', 'age': '', + 'temperament': '', 'temperament_desc': '', 'social_style': '', 'social_desc': '', + 'emotion': '', 'emotion_desc': '', + 'focus': '', 'learning_style': '', 'strengths': [], 'weaknesses': [], + 'classroom_table': [], 'skills': [], 'social_emotional': [], + 'motivation': '', 'instructions': '', + 'teaching_tips': [], 'health_allergy': '', 'health_condition': '', + 'special_attention': '', 'parent_comm': '', 'parent_focus': '', + 'education_fit': '', 'growth_records': [], + 'ai_skills': {}, 'has_ai_section': False, + 'created_date': '', 'updated_date': '', + } + + lines = text.split('\n') + current_section = '' + in_growth = False + in_classroom = False + in_skills = False + in_social = False + in_ai_section = False + + for i, line in enumerate(lines): + stripped = line.strip() + + if re.match(r'^##\s*基本信息', stripped): + current_section = 'basic' + continue + if re.match(r'^##\s*性格特点', stripped): + current_section = 'personality' + continue + if re.match(r'^##\s*学习特点', stripped): + current_section = 'learning' + continue + if re.match(r'^##\s*课堂行为特征', stripped): + current_section = 'classroom' + in_classroom = True + continue + if re.match(r'^##\s*技能评估', stripped): + current_section = 'skills' + in_skills = True + continue + if re.match(r'^##\s*社交与情绪', stripped): + current_section = 'social' + in_social = True + continue + if re.match(r'^##\s*激励方式', stripped): + current_section = 'motivation' + continue + if re.match(r'^##\s*教学建议', stripped): + current_section = 'teaching' + continue + if re.match(r'^##\s*特殊情况', stripped): + current_section = 'special' + continue + if re.match(r'^##\s*家长沟通偏好', stripped): + current_section = 'parent' + continue + if re.match(r'^##\s*成长轨迹', stripped): + current_section = 'growth' + in_growth = True + continue + if re.match(r'^##\s*AI编程技能特征', stripped): + current_section = 'ai_skills' + in_ai_section = True + continue + + if current_section == 'basic': + m = re.match(r'^-\s*\*\*(.+?)\*\*[::]\s*(.*)', stripped) + if m: + key = m.group(1).strip() + val = m.group(2).strip() + if '姓名' in key: data['name'] = val + elif '小名' in key or '昵称' in key: data['nickname'] = val + elif '性别' in key: data['gender'] = val + elif '班级' in key and '上课' not in key: data['class_name'] = val + elif '上课时间' in key: data['class_time'] = val + elif '校区' in key: data['campus'] = val + elif '课程类型' in key: data['course_type'] = val + elif '入学时间' in key: data['enroll_date'] = val + elif '出生日期' in key: data['birthday'] = val + elif '年龄' in key: data['age'] = val + + elif current_section == 'personality': + m = re.match(r'^-\s*\*\*(.+?)\*\*[::]\s*(.*)', stripped) + if m: + key = m.group(1).strip() + val = m.group(2).strip() + if '整体气质' in key or '气质' in key: + data['temperament'] = val + elif '社交风格' in key: + data['social_style'] = val + elif '情绪特点' in key: + data['emotion'] = val + m2 = re.match(r'^\s+-\s*表现[::]\s*(.*)', stripped) + if m2: + desc = m2.group(1).strip() + if data['temperament'] and not data['temperament_desc']: + data['temperament_desc'] = desc + elif data['social_style'] and not data['social_desc']: + data['social_desc'] = desc + elif data['emotion'] and not data['emotion_desc']: + data['emotion_desc'] = desc + + elif current_section == 'learning': + m = re.match(r'^-\s*\*\*(.+?)\*\*[::]\s*(.*)', stripped) + if m: + key = m.group(1).strip() + val = m.group(2).strip() + if '专注力' in key: data['focus'] = val + elif '学习方式' in key: data['learning_style'] = val + if stripped.startswith('- **优势能力**'): + current_section = 'strengths' + continue + if stripped.startswith('- **待发展能力**'): + current_section = 'weaknesses' + continue + + elif current_section == 'strengths': + if stripped.startswith('- **'): + current_section = 'learning' + continue + if stripped.startswith(' - ') or stripped.startswith('- '): + data['strengths'].append(stripped.lstrip('- ').strip()) + + elif current_section == 'weaknesses': + if stripped.startswith('##') or stripped.startswith('- **'): + current_section = 'learning' + continue + if stripped.startswith(' - ') or stripped.startswith('- '): + data['weaknesses'].append(stripped.lstrip('- ').strip()) + + elif current_section == 'classroom' and in_classroom: + if stripped.startswith('##'): + in_classroom = False + current_section = '' + elif '|' in stripped: + data['classroom_table'].append(stripped) + + elif current_section == 'skills' and in_skills: + if stripped.startswith('##'): + in_skills = False + current_section = '' + elif stripped.startswith('- **'): + data['skills'].append(stripped) + + elif current_section == 'social' and in_social: + if stripped.startswith('##'): + in_social = False + current_section = '' + elif stripped.startswith('- **'): + data['social_emotional'].append(stripped) + + elif current_section == 'motivation': + m = re.match(r'^-\s*\*\*(.+?)\*\*[::]\s*(.*)', stripped) + if m: + key = m.group(1).strip() + val = m.group(2).strip() + if '激励' in key: data['motivation'] = val + elif '听指令' in key: data['instructions'] = val + if stripped.startswith('##'): + current_section = '' + + elif current_section == 'teaching': + if stripped.startswith('##'): + current_section = '' + elif re.match(r'^\d+[.、]', stripped) or stripped.startswith('- '): + data['teaching_tips'].append(stripped) + + elif current_section == 'special': + m = re.match(r'^-\s*\*\*(.+?)\*\*[::]\s*(.*)', stripped) + if m: + key = m.group(1).strip() + val = m.group(2).strip() + if '过敏' in key: data['health_allergy'] = val + elif '健康' in key: data['health_condition'] = val + elif '特别关注' in key or '需要' in key: data['special_attention'] = val + if stripped.startswith('##'): + current_section = '' + + elif current_section == 'parent': + m = re.match(r'^-\s*\*\*(.+?)\*\*[::]\s*(.*)', stripped) + if m: + key = m.group(1).strip() + val = m.group(2).strip() + if '沟通方式' in key: data['parent_comm'] = val + elif '关注点' in key: data['parent_focus'] = val + elif '教育理念' in key or '匹配' in key: data['education_fit'] = val + if stripped.startswith('##'): + current_section = '' + + elif current_section == 'growth' and in_growth: + if stripped.startswith('##') and '成长' not in stripped: + in_growth = False + current_section = '' + elif '|' in stripped: + data['growth_records'].append(stripped) + + elif current_section == 'ai_skills' and in_ai_section: + if stripped.startswith('##') and 'AI' not in stripped and '基础' not in stripped and '协作' not in stripped: + in_ai_section = False + current_section = '' + else: + m = re.match(r'^-\s*\*\*(.+?)\*\*[::]\s*(.*)', stripped) + if m: + data['ai_skills'][m.group(1).strip()] = m.group(2).strip() + + m = re.search(r'\*创建日期[::]\s*(.*)', stripped) + if m: data['created_date'] = m.group(1).strip() + m = re.search(r'\*更新日期[::]\s*(.*)', stripped) + if m: data['updated_date'] = m.group(1).strip() + + return data + +def generate_new_profile(data, file_path): + parts = os.path.normpath(file_path).split(os.sep) + class_name = '' + student_name = data['name'] + for i, p in enumerate(parts): + if p == 'profile.md': + if i >= 2: + student_name = parts[i-1] + class_name = parts[i-2] + break + + course_type = data['course_type'] or '' + is_disc = 'DISC' in course_type or '发现' in class_name or '螺丝刀' in course_type + is_aicode = 'AICODE' in course_type or 'AICODE' in class_name or 'AI' in course_type + is_spike = 'SPIKE' in course_type or 'SPIKE' in class_name + is_wedo = 'WEDO' in course_type or 'Wedo' in class_name or 'CREATE' in course_type or '创造' in class_name + + lines = [] + lines.append(f'# 学生画像档案:{student_name}') + lines.append('') + + if is_aicode: + lines.append(f'> 班级:{data["class_name"] or class_name}') + lines.append(f'> 课程:{course_type}') + lines.append(f'> 年级:{data["age"]}') + lines.append(f'> 建档日期:{data["created_date"] or "2026-03-25"}') + lines.append(f'> 状态:✅ 已更新') + else: + lines.append(f'> 班级:{data["class_name"] or class_name}') + lines.append(f'> 课程:{course_type}') + lines.append(f'> 建档日期:{data["created_date"] or "2026-03-25"}') + lines.append(f'> 状态:✅ 已更新') + + lines.append('') + lines.append('---') + lines.append('') + + lines.append('## 一、基础信息') + lines.append('') + lines.append('| 项目 | 内容 |') + lines.append('|------|------|') + lines.append(f'| **姓名** | {data["name"]} |') + if data['nickname']: + lines.append(f'| **小名/昵称** | {data["nickname"]} |') + lines.append(f'| **性别** | {data["gender"]} |') + lines.append(f'| **班级** | {data["class_name"] or class_name} |') + lines.append(f'| **上课时间** | {data["class_time"]} |') + if data['campus']: + lines.append(f'| **校区** | {data["campus"]} |') + lines.append(f'| **课程类型** | {course_type} |') + lines.append(f'| **入学时间** | {data["enroll_date"]} |') + if data['birthday']: + lines.append(f'| **出生日期** | {data["birthday"]} |') + lines.append(f'| **年龄** | {data["age"]} |') + + lines.append('') + lines.append('---') + lines.append('') + + lines.append('## 二、性格气质画像') + lines.append('') + lines.append('### 2.1 气质类型') + if data['temperament']: + lines.append(f'- ✅ **{data["temperament"]}**') + if data['temperament_desc']: + lines.append(f' - {data["temperament_desc"]}') + else: + lines.append('- [ ] 活泼型(外向、精力充沛、反应快)') + lines.append('- [ ] 谨慎型(内向、观察后行动、深思熟虑)') + lines.append('- [ ] 平和型(情绪稳定、适应性良好)') + lines.append('- [ ] 敏感型(细腻、情绪反应强、需要安全感)') + lines.append('- [ ] 混合型(请注明:______)') + + lines.append('') + lines.append('### 2.2 社交互动模式') + if data['social_emotional']: + for item in data['social_emotional']: + lines.append(f'- {item.lstrip("- ")}') + else: + lines.append(f'- **与同伴互动**:{data["social_style"] or "待观察"}') + if data['social_desc']: + lines.append(f' - {data["social_desc"]}') + lines.append('- **与老师互动**:待观察') + lines.append('- **冲突处理方式**:待观察') + + lines.append('') + lines.append('### 2.3 情绪特征') + lines.append(f'- **整体稳定性**:{data["emotion"] or "待观察"}') + if data['emotion_desc']: + lines.append(f' - {data["emotion_desc"]}') + lines.append('- **压力反应**:待观察') + lines.append('- **情绪触发点**:待记录') + + lines.append('') + lines.append('---') + lines.append('') + + lines.append('## 三、学习风格与能力') + lines.append('') + lines.append('### 3.1 学习方式偏好') + lines.append(f'- **信息接收**:{data["learning_style"] or "待观察"}') + lines.append('- **学习节奏**:待观察') + lines.append('- **思考方式**:待观察') + + lines.append('') + lines.append('### 3.2 专注力特征') + lines.append('| 维度 | 评估 |') + lines.append('|------|------|') + lines.append(f'| 平均专注时长 | {data["focus"] or "待观察"} |') + lines.append('| 进入专注所需时间 | 待观察 |') + lines.append('| 抗干扰能力 | 待观察 |') + lines.append('| 专注力维持因素 | 待记录 |') + + lines.append('') + lines.append('### 3.3 能力维度雷达') + lines.append('') + lines.append('| 维度 | 评分 | 具体表现描述 |') + lines.append('|------|:---:|:------------|') + + if is_disc: + dims = ['空间想象', '逻辑思维', '创造力', '精细动作', '语言表达', '问题解决', '颜色形状识别', '收纳与秩序感'] + elif is_aicode: + dims = ['空间想象', '逻辑思维', '创造力', '编程能力', '语言表达', 'AI沟通'] + elif is_spike: + dims = ['空间想象', '逻辑思维', '创造力', '精细动作', '语言表达', '问题解决'] + else: + dims = ['空间想象', '逻辑思维', '创造力', '精细动作', '语言表达', '问题解决'] + + for d in dims: + lines.append(f'| {d} | (待评估) | |') + + lines.append('') + lines.append('### 3.4 优势与待发展') + lines.append('- **核心优势能力**:' + ('、'.join(data['strengths']) if data['strengths'] else '待观察')) + lines.append('- **需要重点培养的能力**:' + ('、'.join(data['weaknesses']) if data['weaknesses'] else '待观察')) + lines.append('- **近期进步最明显的方面**:待观察') + if data['motivation']: + lines.append(f'- **最有效的激励方式**:{data["motivation"]}') + if data['instructions']: + lines.append(f'- **听指令情况**:{data["instructions"]}') + + lines.append('') + lines.append('---') + lines.append('') + + lines.append('## 四、课程表现特征') + lines.append('') + lines.append('### 4.1 课堂行为模式') + lines.append('| 环节 | 典型表现 |') + lines.append('|------|---------|') + if data['classroom_table']: + for row in data['classroom_table']: + if '|' in row and '环节' not in row and '---' not in row: + lines.append(row) + else: + lines.append('| 导入环节 | 待观察 |') + lines.append('| 讲解示范 | 待观察 |') + lines.append('| 动手操作 | 待观察 |') + lines.append('| 调试优化 | 待观察 |') + lines.append('| 分享展示 | 待观察 |') + + lines.append('') + lines.append('### 4.2 作品完成特征') + lines.append('- **完成度**:待观察') + lines.append('- **质量倾向**:待观察') + lines.append('- **创意表现**:待观察') + lines.append('- **细节处理**:待观察') + + if is_disc and data['skills']: + lines.append('') + lines.append('### 4.3 精细动作技能特征') + for s in data['skills']: + lines.append(f'- {s.lstrip("- ")}') + + lines.append('') + lines.append('### 4.3 遇到困难时的反应') + lines.append('- **第一反应**:待观察') + lines.append('- **能坚持尝试次数**:待观察') + lines.append('- **最有效的鼓励方式**:' + (data['motivation'] or '待观察')) + + lines.append('') + lines.append('---') + lines.append('') + + lines.append('## 五、特殊事项记录') + lines.append('') + lines.append('### 5.1 健康信息') + lines.append(f'- **过敏史**:{data["health_allergy"]}') + lines.append(f'- **健康状况**:{data["health_condition"]}') + lines.append('- **需要特别关注**:' + (data['special_attention'] or '')) + + lines.append('') + lines.append('### 5.2 家庭背景(简要)') + lines.append('- **家庭成员**:') + lines.append('- **主要接送人**:') + lines.append('- **家庭特殊情况**:') + lines.append('- **在家乐高/编程情况**:') + + lines.append('') + lines.append('---') + lines.append('') + + lines.append('## 六、家长沟通档案') + lines.append('') + lines.append('### 6.1 家长基本信息') + lines.append('| 关系 | 称呼 | 职业特点 | 教育理念 |') + lines.append('|------|------|---------|---------|') + lines.append('| 父亲 | | | |') + lines.append('| 母亲 | | | |') + lines.append('| 主要联系人 | | | |') + + lines.append('') + lines.append('### 6.2 沟通偏好') + lines.append(f'- **首选沟通方式**:{data["parent_comm"]}') + lines.append('- **合适联系时间**:') + lines.append('- **期望沟通频率**:') + lines.append('- **信息接收风格**:') + + lines.append('') + lines.append('### 6.3 家长关注点与期待') + lines.append(f'- **最关注的方面**:{data["parent_focus"]}') + lines.append('- **对孩子在这门课的期待**:') + lines.append('- **过往反馈过的顾虑**:') + lines.append(f'- **与机构理念的契合度**:{data["education_fit"]}') + + lines.append('') + lines.append('### 6.4 历史沟通记录') + lines.append('| 日期 | 方式 | 主题 | 要点记录 |') + lines.append('|------|------|------|---------|') + lines.append('| | | | |') + + lines.append('') + lines.append('---') + lines.append('') + + lines.append('## 七、成长轨迹') + lines.append('') + lines.append('| 时间 | 关键事件 | 能力发展 |') + lines.append('|-----|---------|---------|') + if data['growth_records']: + for row in data['growth_records']: + if '|' in row and '时间' not in row and '---' not in row: + lines.append(row) + else: + lines.append('| 入学初 | | |') + + lines.append('') + lines.append('---') + lines.append('') + + if is_aicode and data['ai_skills']: + lines.append('## 四、AI编程技能特征') + lines.append('') + lines.append('### 4.1 基础操作能力') + lines.append('') + lines.append('| 能力项 | 水平 | 具体表现 |') + lines.append('|--------|:---:|----------|') + for k, v in data['ai_skills'].items(): + if '鼠标' in k or '键盘' in k or '抽象' in k: + lines.append(f'| {k} | {v} | |') + lines.append('') + lines.append('### 4.2 Prompt与AI协作能力') + lines.append('') + lines.append('| 技能维度 | 表现描述 |') + lines.append('|----------|----------|') + for k, v in data['ai_skills'].items(): + if 'Prompt' in k or '迭代' in k or '幻觉' in k or 'Few' in k or '上下文' in k or '代码缝合' in k or '逻辑' in k: + lines.append(f'| {k} | {v} |') + lines.append('') + lines.append('---') + lines.append('') + + if data['teaching_tips']: + lines.append('## 八、教学建议') + lines.append('') + for tip in data['teaching_tips']: + lines.append(tip) + lines.append('') + lines.append('---') + lines.append('') + + lines.append('') + created = data['created_date'] or '2026-03-25' + updated = data['updated_date'] or created + lines.append(f'*创建日期:{created}*') + lines.append(f'*最后更新:{updated}*') + + return '\n'.join(lines) + +def fix_wrong_title(text, file_path): + parts = os.path.normpath(file_path).split(os.sep) + student_name = '' + for i, p in enumerate(parts): + if p == 'profile.md' and i >= 2: + student_name = parts[i-1] + break + + lines = text.split('\n') + if lines and lines[0].strip() == '# 用户画像': + lines[0] = f'# 学生画像档案:{student_name}' + return '\n'.join(lines) + +def convert_unique_format(text, file_path): + parts = os.path.normpath(file_path).split(os.sep) + student_name = '' + for i, p in enumerate(parts): + if p == 'profile.md' and i >= 2: + student_name = parts[i-1] + break + + data = { + 'name': student_name, 'nickname': '', 'gender': '', 'class_name': '', + 'class_time': '', 'campus': '', 'course_type': '', 'enroll_date': '', + 'birthday': '', 'age': '', 'temperament': '', 'temperament_desc': '', + 'social_style': '', 'social_desc': '', 'emotion': '', 'emotion_desc': '', + 'focus': '', 'learning_style': '', 'strengths': [], 'weaknesses': [], + 'classroom_table': [], 'skills': [], 'social_emotional': [], + 'motivation': '', 'instructions': '', 'teaching_tips': [], + 'health_allergy': '', 'health_condition': '', 'special_attention': '', + 'parent_comm': '', 'parent_focus': '', 'education_fit': '', + 'growth_records': [], 'ai_skills': {}, 'has_ai_section': False, + 'created_date': '', 'updated_date': '', + } + + lines = text.split('\n') + for line in lines: + stripped = line.strip() + m = re.search(r'\*建档日期[::]\s*(.*)', stripped) + if m: data['created_date'] = m.group(1).strip() + m = re.search(r'\*更新日期[::]\s*(.*)', stripped) + if m: data['updated_date'] = m.group(1).strip() + + if '班级' in stripped and ':' in stripped and not data['class_name']: + cm = re.match(r'.*班级[::]\s*(.*)', stripped) + if cm: data['class_name'] = cm.group(1).strip() + if '课程类型' in stripped and ':' in stripped: + cm = re.match(r'.*课程类型[::]\s*(.*)', stripped) + if cm: data['course_type'] = cm.group(1).strip() + if '年龄段' in stripped and ':' in stripped: + cm = re.match(r'.*年龄段[::]\s*(.*)', stripped) + if cm: data['age'] = cm.group(1).strip() + if '上课时间' in stripped and ':' in stripped: + cm = re.match(r'.*上课时间[::]\s*(.*)', stripped) + if cm: data['class_time'] = cm.group(1).strip() + + return generate_new_profile(data, file_path) + +def process_profile(file_path): + with open(file_path, 'r', encoding='utf-8') as f: + text = f.read() + + fmt = detect_format(text) + + if fmt == 'new': + return False + + if fmt == 'new_structure_wrong_title': + new_text = fix_wrong_title(text, file_path) + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_text) + return True + + if fmt == 'old_list': + data = parse_old_list_format(text, file_path) + new_text = generate_new_profile(data, file_path) + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_text) + return True + + if fmt == 'unique': + new_text = convert_unique_format(text, file_path) + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_text) + return True + + return False + +def main(): + updated = 0 + skipped = 0 + errors = 0 + + for root, dirs, files in os.walk(CLASS_DIR): + for f in files: + if f != 'profile.md': + continue + file_path = os.path.join(root, f) + try: + if process_profile(file_path): + updated += 1 + rel = os.path.relpath(file_path, CLASS_DIR) + print(f' ✅ 已更新: {rel}') + else: + skipped += 1 + except Exception as e: + errors += 1 + rel = os.path.relpath(file_path, CLASS_DIR) + print(f' ❌ 错误: {rel} - {e}') + + print(f'\n{"="*50}') + print(f'更新完成!') + print(f' ✅ 已更新: {updated} 个文件') + print(f' ⏭️ 已跳过(已是最新格式): {skipped} 个文件') + print(f' ❌ 错误: {errors} 个文件') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/src/unify_summaries.py b/src/unify_summaries.py new file mode 100644 index 0000000..d5c8156 --- /dev/null +++ b/src/unify_summaries.py @@ -0,0 +1,227 @@ +import os +import re + +CLASS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.claude', 'memory', 'class') + +TEMPLATE = '''# 成长素材 + +> 收集学生的作品照片、视频、作品描述等成长证据 + +## 目录结构 + +``` +成长素材/ +├── 作品照片/ # 课堂作品照片 +├── 视频记录/ # 课堂表现视频 +├── 作品图纸/ # 设计草图、程序截图 +├── 家长分享/ # 家长提供的家庭延伸作品 +└── 特别记录/ # 获奖、展示等特殊时刻 +``` + +## 素材记录格式 + +```markdown +### YYYY-MM-DD | 课程代码:XXX-XXX + +**作品名称**: +**作品描述**: +**技术亮点**: +**学生解说**(如有): +**教师点评**: + +**文件位置**: +- 照片:作品照片/YYYYMM_XXX_001.jpg +- 视频:视频记录/YYYYMM_XXX_001.mp4 + +--- +``` + +## 作品记录列表 + +### 代表作品 + +| 日期 | 课程 | 作品名称 | 亮点 | 文件位置 | +|-----|------|---------|------|---------| +| | | | | | + +### 成长对比 + +| 时间 | 作品 | 能力体现 | 进步说明 | +|-----|------|---------|---------| +| 第1周 | | | | +| 第4周 | | | | +| 第8周 | | | | +| 第12周 | | | | + +--- +*创建日期:2026-03-25* +''' + +def is_already_template(text): + return '目录结构' in text and '素材记录格式' in text and '作品记录列表' in text + +def extract_existing_data(text, file_path): + parts = os.path.normpath(file_path).split(os.sep) + student_name = '' + class_name = '' + for i, p in enumerate(parts): + if p == 'summary' and i >= 2: + student_name = parts[i-1] + class_name = parts[i-2] + break + + data_rows = [] + in_table = False + for line in text.split('\n'): + stripped = line.strip() + if '|' in stripped and not stripped.startswith('| ---') and not stripped.startswith('|---'): + cells = [c.strip() for c in stripped.split('|') if c.strip()] + if len(cells) >= 3: + has_date = bool(re.match(r'\d{4}-\d{2}-\d{2}', cells[0])) + if has_date: + data_rows.append(cells) + + return student_name, class_name, data_rows + +def generate_summary(text, file_path): + student_name, class_name, data_rows = extract_existing_data(text, file_path) + + if is_already_template(text): + return None + + if data_rows: + table_rows = [] + for row in data_rows: + table_rows.append('| ' + ' | '.join(row[:5]) + ' |') + + detail_sections = [] + for row in data_rows: + if len(row) >= 2: + detail_sections.append(f'''### {row[0]}:{row[1] if len(row) > 1 else ''} +- **作品名称**:{row[1] if len(row) > 1 else ''} +- **课程**:{row[0]} +- **成长亮点**:{row[3] if len(row) > 3 else ''}''') + + result = f'''# 成长素材 + +> {student_name} - {class_name} + +--- + +## 作品记录 + +| 日期 | 课程 | 作品名称 | 亮点 | +|-----|------|---------|------| +{chr(10).join(table_rows)} + +--- + +## 作品详情 + +{chr(10).join(detail_sections)} + +--- +*学生:{student_name} | 班级:{class_name}* +*创建日期:2026-03-25*''' + return result + + result = f'''# 成长素材 + +> 收集{student_name}的作品照片、视频、作品描述等成长证据 + +## 目录结构 + +``` +成长素材/ +├── 作品照片/ # 课堂作品照片 +├── 视频记录/ # 课堂表现视频 +├── 作品图纸/ # 设计草图、程序截图 +├── 家长分享/ # 家长提供的家庭延伸作品 +└── 特别记录/ # 获奖、展示等特殊时刻 +``` + +## 素材记录格式 + +```markdown +### YYYY-MM-DD | 课程代码:XXX-XXX + +**作品名称**: +**作品描述**: +**技术亮点**: +**学生解说**(如有): +**教师点评**: + +**文件位置**: +- 照片:作品照片/YYYYMM_XXX_001.jpg +- 视频:视频记录/YYYYMM_XXX_001.mp4 + +--- +``` + +## 作品记录列表 + +### 代表作品 + +| 日期 | 课程 | 作品名称 | 亮点 | 文件位置 | +|-----|------|---------|------|---------| +| | | | | | + +### 成长对比 + +| 时间 | 作品 | 能力体现 | 进步说明 | +|-----|------|---------|---------| +| 第1周 | | | | +| 第4周 | | | | +| 第8周 | | | | +| 第12周 | | | | + +--- +*学生:{student_name} | 班级:{class_name}* +*创建日期:2026-03-25*''' + return result + +def process_summary(file_path): + with open(file_path, 'r', encoding='utf-8') as f: + text = f.read() + + new_text = generate_summary(text, file_path) + if new_text is None: + return False + + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_text) + return True + +def main(): + updated = 0 + skipped = 0 + errors = 0 + + for root, dirs, files in os.walk(CLASS_DIR): + if 'summary' not in root.split(os.sep): + continue + + for f in files: + if not f.endswith('.md'): + continue + file_path = os.path.join(root, f) + try: + if process_summary(file_path): + updated += 1 + rel = os.path.relpath(file_path, CLASS_DIR) + print(f' ✅ 已更新: {rel}') + else: + skipped += 1 + except Exception as e: + errors += 1 + rel = os.path.relpath(file_path, CLASS_DIR) + print(f' ❌ 错误: {rel} - {e}') + + print(f'\n{"="*50}') + print(f'更新完成!') + print(f' ✅ 已更新: {updated} 个文件') + print(f' ⏭️ 已跳过(已是最新格式): {skipped} 个文件') + print(f' ❌ 错误: {errors} 个文件') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/课评系统.html b/课评系统.html new file mode 100644 index 0000000..c5ccbdb --- /dev/null +++ b/课评系统.html @@ -0,0 +1,1412 @@ + + + + + +小Q老师 - 课评生成系统 v6.0 + + + +
+ +
+ +
+

小Q老师 · 课评系统

+
2026春季学期 | Form-First模式 | v6.0
+
+ + +
+ + + + + + + + + + + +
+ + +
+ + +
+ + +
+ +
+

🏷️ 课堂观察标签

+
+ 标签目标: + 当前学生 + (点击切换) +
+
+ +
+ + +
+ +
+
+
1. 选择周数
+ +
+
+
2. 选择周几
+ +
+
+
3. 选择班级
+ +
+ + +
📅
+
+ + +
+
+
+
课程主题
+
-
+
+
+
课程代码
+
-
+
+
+
核心知识点
+
-
+
+
+
+ + +
+
+ + +
+ + +
+ 📌 速记符号参考:
+ gj# 观望#分钟 · + zd# 主动搭#层 · + zt 自己调整 · + zz# 专注#分钟 · + bz 帮助同学 · + tw 提问 · + wc 完成 · + cx 创新 · + 开心 · + 稳定 · + 低落 · + ++ 比上周进步 +
+ + +
+
+ 🔄 + 补课/体验学生 +
+
+
+
+ +
+ + + +
+
+ +
+
+ +
+ + +
+ + + +
+ + +
+

⬇️ 输出结果(复制保存,或交给Claude生成课评)

+
+ +
💡 将内容粘贴给Claude,使用keping-advanced技能生成并自动保存课评
+
+
+
+
+ + + + + \ No newline at end of file