赋能培训人 · 培训系统

请先登录以进入工作台
默认账号 / 密码:Coooffeely / hzg12345

赋能培训人

培训系统工作台
⏻ 退出

培训需求

填写后一键生成方案
① 需求分析
② 课程大纲
③ 培训课件
④ 培训海报
⑤ AI陪练
⑥ 考核评估
⑦ 微课专家手动
在左侧填入培训需求,点击「生成培训方案」
系统将按五段链路真实产出可交付物

微课服务配置

高级:配音 / 视觉 / LLM(点击展开)

微课专家(手动出片)

基于已生成的「③培训课件」自动萃取分镜脚本,调用你配置的微课服务出片(网页播放器:画面 + 中文配音,零依赖)。需先生成培训方案。此步骤不随主链路自动执行,按需手动触发。

生成微课视频

(请先在左侧生成培训方案,再回到本页查看分镜预览)
`; downloadFile(`课件_${STATE.theme}.html`,doc); } /* ---------- ④ 海报 ---------- */ let POSTER_MD=""; function renderPoster(){ const benefit=STATE.goals[0]||"系统赋能 · 实战为王"; const modules=OUTLINE?OUTLINE.modules.slice(0,6):[]; POSTER_MD=`# 培训海报文案 · ${STATE.theme}\n\n## 主视觉海报\n主标题:${STATE.theme}\n副标题:面向 ${STATE.audience} · ${STATE.duration} · ${STATE.headcount}人小班\n核心收益:${benefit}\n\n## 详细内容海报\n课程模块:\n`+modules.map(m=>`- ${m.key}·${m.name}(${m.min}′)`).join("\n")+`\n时间地点:待定\n讲师:资深实战导师\n报名:扫码 / 内部系统报名`; const kv=buildKVPosterHTML(SKINS[POSTER_SKIN],benefit,modules); const detail=buildDetailPosterHTML(SKINS[POSTER_SKIN],modules); $("#posterBody").innerHTML=`

双海报预览(点击色块切换主视觉皮肤)

${kv}
${detail}

左:主视觉海报(9:16,朋友圈/招生) · 右:详细内容海报(16:9,课程通知/钉邮)

`; const row=$("#skinRow"); Object.entries(SKINS).forEach(([k,v])=>{ const d=el("div","skin-dot",""); d.style.background=v.bg; d.title=v.name; d.onclick=()=>{POSTER_SKIN=k; renderPoster();}; row.appendChild(d); }); } function buildKVPosterHTML(skin,benefit,modules){ const outlineHtml=modules.slice(0,5).map(m=>`
${esc(m.key)} · ${esc(m.name)}
`).join(""); return `
TRAINING · 赋能培训人
${esc(STATE.theme)}
面向 ${esc(STATE.audience)} · ${esc(STATE.duration)} · ${STATE.headcount}人小班
课程大纲
${outlineHtml}
时间:待定
地点:待定
讲师:资深实战导师
报名:扫码 / 内部系统报名
`; } function buildDetailPosterHTML(skin,modules){ const modHtml=modules.map(m=>`
${m.key} · ${esc(m.name)}
${m.min}′ · ${esc(m.form)}
`).join(""); return `
COURSE DETAIL
${esc(STATE.theme)}
面向 ${esc(STATE.audience)} · ${esc(STATE.duration)} · ${STATE.headcount}人小班
课程模块
${modHtml}
报名信息
时间:待定
地点:待定
讲师:资深实战导师
对象:${esc(STATE.audience)}
报名:扫码 / 内部系统报名
二维码
占位
`; } function downloadPosterKV(){ const benefit=STATE.goals[0]||"系统赋能 · 实战为王"; const modules=OUTLINE?OUTLINE.modules.slice(0,5):[]; const outlineHtml=modules.map(m=>`
${esc(m.key)} · ${esc(m.name)}
`).join(""); const html=`主视觉海报 · ${esc(STATE.theme)}
TRAINING · 赋能培训人
${esc(STATE.theme)}
面向 ${esc(STATE.audience)} · ${esc(STATE.duration)} · ${STATE.headcount}人小班
课程大纲
${outlineHtml}
时间:待定
地点:待定
讲师:资深实战导师
报名:扫码 / 内部系统报名
`; downloadFile(`海报_主视觉_${STATE.theme}.html`,html); } function downloadPosterDetail(){ const modules=OUTLINE?OUTLINE.modules.slice(0,6):[]; const modHtml=modules.map(m=>`
${m.key} · ${esc(m.name)}
${m.min}′ · ${esc(m.form)}
`).join(""); const html=`详细内容海报 · ${esc(STATE.theme)}
COURSE DETAIL
${esc(STATE.theme)}
面向 ${esc(STATE.audience)} · ${esc(STATE.duration)} · ${STATE.headcount}人小班
课程模块
${modHtml}
报名信息
时间:待定
地点:待定
讲师:资深实战导师
对象:${esc(STATE.audience)}
报名:扫码 / 内部系统报名
二维码
占位
`; downloadFile(`海报_详细内容_${STATE.theme}.html`,html); } /* ---------- ⑤ AI陪练 ---------- */ function renderCoach(){ const a=AUDIENCE_PROFILE[STATE.audience]; const g=STATE.goals[0]||"业务目标"; COACH={ role:STATE.audience+"代表 · 学员/客户", persona:`性格:${STATE.audience==="中高层"?"理性谨慎、时间宝贵、关注ROI":STATE.audience==="新员工"?"紧张害羞、怕说错、需要鼓励":"务实直接、带点戒备、看重实效"};情境:在${STATE.theme}场景中与你互动。`, scenario:`模拟一次${STATE.theme}的实战对话,重点考察你对"${g}"的落地能力。`, seeds:[ "这个培训/方案听起来挺好,但和我现在的工作有什么关系?", "我之前试过类似的,没什么用,你说说凭什么这次不一样?", "你说的方法我懂,但遇到难缠的客户/下属我根本用不上。" ], dims:[["共情",20],["表达清晰",20],["专业度",25],["应变",20],["目标达成",15]], review:[`是否先共情再给方案(而非直接推销)`,`是否用"${g}"相关业务语言而非空泛概念`,`是否在对方异议时做了澄清与确认`], md:`# AI陪练剧本 · ${STATE.theme}\n角色:${STATE.audience}代表\n人格:${a.p}\n情境:${g}\n评分维度:${COACH? "":""}` }; COACH.md=`# AI陪练剧本 · ${STATE.theme}\n角色:${COACH.role}\n人格:${COACH.persona}\n情境:${COACH.scenario}\n种子语料:\n${COACH.seeds.map(s=>"- "+s).join("\n")}\n评分维度:${COACH.dims.map(d=>d[0]+d[1]+"%").join(" / ")}\n复盘要点:\n${COACH.review.map(r=>"- "+r).join("\n")}`; const dimsHtml=COACH.dims.map(d=>`${d[0]} ${d[1]}%`).join(""); const seedsHtml=COACH.seeds.map(s=>`
${esc(s)}
`).join(""); $("#coachBody").innerHTML=`

陪练剧本

角色
${esc(COACH.role)}
人格设定
${esc(COACH.persona)}
情境
${esc(COACH.scenario)}

评分维度(双轨:规则卡底线 + 模型评判)

${dimsHtml}

复盘要点

陪练模拟(规则引擎演示)

${seedsHtml}
👋 我是你的${esc(STATE.audience)},准备好了就跟我聊聊"${esc(STATE.theme)}"吧。

演示版用关键词规则回应;接入真实 LLM 后可做语义级角色扮演与评分。

`; } function coachSend(){ const inp=$("#coachIn"); const v=inp.value.trim(); if(!v)return; const box=$("#chatBox"); box.appendChild(el("div","msg me",esc(v))); inp.value=""; // 规则反馈 let fb; if(/关系|有用|为什么|凭什么|不一样/.test(v)) fb="(对方稍缓)你说得有点道理,但我还是想知道具体怎么落地…你能举个我这个岗位的例子吗?"; else if(/案例|例子|比如|场景/.test(v)) fb="(点头)这个例子我能代入。那如果对方还是不配合,我下一步该怎么做?"; else if(/共情|理解|感受|明白/.test(v)) fb="(语气软化)嗯,你先听我说完,这感觉还行。那你具体能帮我解决什么?"; else fb="(略皱眉)听起来还是有点虚。你能不能说点我能马上用的?"; setTimeout(()=>{box.appendChild(el("div","msg bot",esc(fb)));box.scrollTop=box.scrollHeight;},400); box.scrollTop=box.scrollHeight; } /* ---------- ⑥ 考核 ---------- */ let ASSESS_MD=""; function renderAssess(O){ // 依据大纲知识点出题 const knowMap={}; O.modules.forEach(m=>{knowMap[m.know]=m.key;}); const knows=Object.keys(knowMap); ASSESS_QS=[ {type:"single",q:`关于「${STATE.theme}」,以下哪项最符合本次培训的核心目标?`,opts:["统一标准动作并可在场景中应用","了解概念即可","完成考试拿证书","听讲师分享经验"],ans:0,knows:knows[2]||"核心",diff:"中"}, {type:"single",q:`在${STATE.audience}的${knowMap[knows[0]]||"导入"}环节,最合适的开场方式是?`,opts:["直接讲理论","用真实业务场景切入引发共鸣","播放长视频","点名批评"],ans:1,knows:knows[0]||"导入",diff:"易"}, {type:"multiple",q:`以下哪些属于「${STATE.theme}」落地时的关键要点?(多选)`,opts:["标准步骤拆解","高/低绩效样本对比","忽视异议直接推进","结合业务目标实战"],ans:[0,1,3],knows:knows[2]||"核心",diff:"中"}, {type:"fill",q:`请写出「${STATE.theme}」中你印象最深的一个标准步骤/话术结构:`,ans:["步骤","结构","话术","流程"],knows:knows[2]||"核心",diff:"中"}, {type:"reflect",q:`结合训后30天行动计划,写明你将在什么场景下、如何用本次所学解决一个真实问题:`,ans:[],knows:"综合",diff:"难",open:true} ]; let html=`

考核题库(${ASSESS_QS.length}题 · 及格线 80 分)

每题关联大纲知识点,支持单选/多选/填空/反思。下方可交互作答,提交后即时判分并出长图文报告。

`; $("#assessBody").innerHTML=html; const qb=$("#quizBox"); ASSESS_QS.forEach((q,i)=>{ const c=el("div","q"); let inner=`
${i+1}. ${esc(q.q)}
题型:${typeName(q.type)} 知识点:${esc(q.knows)} 难度:${q.diff}
`; if(q.type==="single"||q.type==="multiple"){ q.opts.forEach((o,oi)=>{ const id=`q${i}_${oi}`; inner+=``; }); }else if(q.type==="fill"){ inner+=``; }else{ inner+=``; } c.innerHTML=inner; qb.appendChild(c); }); // 柯氏 const kirk=`

柯氏四级评估设计(L1-L4)

层级评估内容方式时点
L1 反应满意度、 relevance课后问卷结营当天
L2 学习知识/技能掌握本页测验 + 陪练得分训中/训后
L3 行为岗位行为改变上级观测 + 30/60/90天复盘训后30-90天
L4 结果业务指标改善${esc(STATE.goals[0]||"业务目标")} 前后对比训后季度
及格线默认 80 分(可调);未达标须安排补考/重修,L3/L4 需业务侧配合采集。
`; qb.insertAdjacentHTML("beforeend",kirk); ASSESS_MD=`# 考核方案 · ${STATE.theme}\n及格线80分\n题库:\n`+ASSESS_QS.map((q,i)=>`${i+1}. [${typeName(q.type)}] ${q.q}(知识点:${q.knows})`).join("\n")+`\n\n柯氏L1-L4评估见面板。`; } function typeName(t){return {single:"单选",multiple:"多选",fill:"填空",reflect:"反思"}[t];} function gradeQuiz(){ let score=0,total=ASSESS_QS.length,detail=""; ASSESS_QS.forEach((q,i)=>{ let ok=false,userAns=""; if(q.type==="single"){const s=document.querySelector(`input[name=q${i}]:checked`);userAns=s?s.value:"未答";ok=(+userAns===q.ans);} else if(q.type==="multiple"){const cs=[...document.querySelectorAll(`input[name=q${i}]:checked`)].map(x=>+x.value).sort();const a=[...q.ans].sort();ok=(cs.length===a.length&&cs.every((v,k)=>v===a[k]));userAns=cs.join(",")||"未答";} else if(q.type==="fill"){const v=(document.getElementById(`q${i}`).value||"").trim();userAns=v;ok=q.ans.some(k=>v.includes(k));} else{const v=(document.getElementById(`q${i}`).value||"").trim();userAns=v;ok=v.length>10; /*反思开放,有内容即过*/} if(ok)score++; const pct=Math.round(score/total*100); detail+=`
${i+1}. ${ok?'✓ 正确':'✗ 待加强'} 知识点:${esc(q.knows)} 你的作答:${esc(userAns)||"(空)"}${q.type!=='reflect'?` 标准:${Array.isArray(q.ans)?q.ans.join('/'):q.ans}`:''}
`; }); const pct=Math.round(score/total*100); const pass=pct>=80; $("#quizResult").innerHTML=`
${pct}

${pass?'达标(≥80)':'未达标,需补考/重修'}

答对 ${score}/${total} 题 正确率 ${pct}%

逐题回顾

${detail}
`; } /* ---------- 标签切换 ---------- */ document.querySelectorAll(".tab").forEach(t=>t.onclick=()=>switchTab(t.dataset.t)); function switchTab(t){ document.querySelectorAll(".tab").forEach(x=>x.classList.toggle("active",x.dataset.t===t)); document.querySelectorAll(".panel").forEach(p=>p.classList.toggle("active",p.id==="p-"+t)); if(t==="micro"){ loadMicroCfg(); refreshMicroPreview(); } } /* ---------- 导出 ---------- */ function exportMD(which){ if(!STATE)return; const map={need:STATE._need,outline:STATE._outline,course:STATE._course,poster:STATE._poster,coach:STATE._coach,assess:STATE._assess}; const nameMap={need:"需求分析",outline:"课程大纲",course:"课件清单",poster:"海报文案",coach:"陪练剧本",assess:"考核方案"}; downloadFile(`${nameMap[which]}_${STATE.theme}.md`, map[which]||""); } function downloadFile(name,content){ const blob=new Blob([content],{type:"text/plain;charset=utf-8"}); const a=document.createElement("a");a.href=URL.createObjectURL(blob);a.download=name;a.click(); setTimeout(()=>URL.revokeObjectURL(a.href),1000); } /* ---------- 示例 ---------- */ $("#sampleBtn").onclick=()=>{ $("#f-theme").value="新员工销售话术实战训练"; $("#f-audience").value="新员工"; $("#f-goal").value="新人上手慢、话术不统一、首月转化率低于目标20%"; $("#f-duration").value="1天"; $("#f-headcount").value="30"; $("#f-material").value="已有产品手册PDF、标准话术SOP v2"; $("#f-start").value="需求"; }; $("#genBtn").onclick=generate; /* ---------- ⑦ 微课专家(手动出片) ---------- */ let MICRO_CFG={baseUrl:"http://127.0.0.1:8000",user:"Coooffeely",pass:"hzg12345",voice:"zh-CN-YunyangNeural",style:"corporate-blue",dur:6,llmUrl:"",llmKey:"",llmModel:""}; function loadMicroCfg(){ try{const s=localStorage.getItem("micro_api_cfg");if(s)Object.assign(MICRO_CFG,JSON.parse(s));}catch(e){} const set=(id,v)=>{const e=document.getElementById(id);if(e)e.value=v;}; set("mc-base",MICRO_CFG.baseUrl);set("mc-user",MICRO_CFG.user);set("mc-pass",MICRO_CFG.pass); set("mc-voice",MICRO_CFG.voice);set("mc-style",MICRO_CFG.style); set("mc-dur",MICRO_CFG.dur);set("mc-llm-url",MICRO_CFG.llmUrl); set("mc-llm-key",MICRO_CFG.llmKey);set("mc-llm-model",MICRO_CFG.llmModel); } function saveMicroCfg(){ MICRO_CFG={ baseUrl:($("#mc-base").value.trim()||"http://127.0.0.1:8000"), user:$("#mc-user").value.trim(), pass:$("#mc-pass").value, voice:$("#mc-voice").value, style:$("#mc-style").value, dur:(+$("#mc-dur").value||6), llmUrl:$("#mc-llm-url").value.trim(), llmKey:$("#mc-llm-key").value.trim(), llmModel:$("#mc-llm-model").value.trim() }; localStorage.setItem("micro_api_cfg",JSON.stringify(MICRO_CFG)); const st=$("#mc-cfg-status");st.textContent="已保存 ✓";setTimeout(()=>st.textContent="",2200); } function toggleMcCfg(force){ const el=document.getElementById("mcCfg"); const show=(force===undefined)?!el.classList.contains("show"):force; el.classList.toggle("show",show); } // 从已生成课件萃取分镜脚本(供微课服务出片) function buildMicroBrief(){ if(!OUTLINE)return null; const modSlides=OUTLINE.modules.map(m=>({ title:`${m.no}. ${m.key}·${m.name}`, bullets:(m.points&&m.points.length)?m.points:[m.name] })); const dur=(+$("#mc-dur").value)||MICRO_CFG.dur||6; return { topic:STATE.theme, grade:STATE.audience, duration_min:dur, slides:[{title:STATE.theme,bullets:[STATE.audience,"主讲:微课专家",`时长约 ${dur} 分钟`]},...modSlides] }; } function refreshMicroPreview(){ const spec=buildMicroBrief(); const box=$("#mc-brief-preview"); if(!spec){box.className="muted";box.innerHTML="(请先在左侧生成培训方案,再回到本页查看分镜预览)";return;} box.className=""; box.innerHTML=`
将向微课服务发送以下分镜(共 ${spec.slides.length} 页):
`+ spec.slides.map((s,i)=>`
${i+1}. ${esc(s.title)} — ${(s.bullets||[]).slice(0,2).join(" / ")}
`).join(""); } async function generateMicro(){ if(!STATE||!OUTLINE){alert("请先在左侧生成培训方案(五段链路),再回到本页生成微课。");return;} loadMicroCfg(); const base=($("#mc-base").value.trim()||"http://127.0.0.1:8000").replace(/\/$/,''); const user=$("#mc-user").value.trim(), pass=$("#mc-pass").value; if(!user||!pass){alert("请先在上方配置区填写 API 账号和密码(微课服务已启用 Basic Auth 保护)。");return;} const voice=$("#mc-voice").value, style=$("#mc-style").value, dur=+$("#mc-dur").value||6; const llmUrl=$("#mc-llm-url").value.trim(), llmKey=$("#mc-llm-key").value.trim(), llmModel=$("#mc-llm-model").value.trim(); const spec=buildMicroBrief(); if(!spec)return; spec.duration_min=dur; const llm={}; if(llmKey)llm.api_key=llmKey; if(llmUrl)llm.base_url=llmUrl; if(llmModel)llm.model=llmModel; const card=$("#mc-result-card"); card.style.display="block"; const headers={"Content-Type":"application/json"}; if(user&&pass)headers["Authorization"]="Basic "+btoa(unescape(encodeURIComponent(user+":"+pass))); let jobId; setMc(0,"正在提交到微课服务…"); try{ const r=await fetch(base+"/api/generate",{method:"POST",headers,body:JSON.stringify({spec,voice,style,llm})}); if(!r.ok)throw new Error("HTTP "+r.status); const j=await r.json(); jobId=j.job_id; if(!jobId)throw new Error("未返回 job_id"); }catch(e){ setMc(0,"❌ 提交失败:"+e.message); showBriefFallback(spec,e); return; } let outs=null; for(let i=0;i<150;i++){ await new Promise(r=>setTimeout(r,2000)); try{ const jr=await fetch(base+"/api/job/"+jobId,{headers}); const j=await jr.json(); setMc(j.progress||0,j.message||"生成中…"); if(j.done){ if(j.error){setMc(100,"❌ 失败:"+j.error);showBriefFallback(spec,new Error(j.error));return;} outs=j.outputs; break; } }catch(e){ setMc(0,"❌ 轮询失败:"+e.message); return; } } if(!outs){setMc(0,"超时:生成超过 5 分钟,请在微课服务后台查看任务 "+jobId);return;} const playerUrl=base+"/api/output/"+jobId+"/player.html"; $("#mc-embed").innerHTML= `

主交付为网页播放器 player.html(画面 + 中文配音,零依赖)。若 iframe 被拦截,点「新窗口打开」。音频依赖 edge-tts 联网;离线时画面/教案仍产出。

`; setMc(100,"✅ 生成完成"); } function setMc(p,msg){const bar=$("#mc-bar");if(bar)bar.style.width=(p||0)+"%";const m=$("#mc-msg");if(m)m.textContent=msg;} function showBriefFallback(spec,e){ $("#mc-embed").innerHTML= `
API 调用未成功(${esc(e.message||e)})。可手动将下方 brief 导入 project_91 微课系统后端出片,或检查服务地址 / CORS / 服务是否已启动。
${esc(JSON.stringify(spec,null,2))}
`; } function downloadMicroBrief(){ const spec=buildMicroBrief(); if(!spec){alert("请先生成培训方案。");return;} downloadFile(`微课brief_${STATE.theme}.json`,JSON.stringify(spec,null,2)); } /* ---------- 首页登录闸门 ---------- */ const LOGIN_USER="Coooffeely", LOGIN_PASS="hzg12345"; function initLogin(){ // 演示版:不设登录闸门,直接进入工作台 const ov=document.getElementById("loginOverlay"); if(ov) ov.classList.add("hide"); } function doLogin(){ const u=document.getElementById("loginUser").value.trim(); const p=document.getElementById("loginPass").value; const err=document.getElementById("loginErr"); if(u===LOGIN_USER && p===LOGIN_PASS){ localStorage.setItem("training_logged_in","1"); document.getElementById("loginOverlay").classList.add("hide"); err.textContent=""; }else{ err.textContent="账号或密码错误,请重试"; } } function doLogout(){ localStorage.removeItem("training_logged_in"); document.getElementById("loginUser").value=""; document.getElementById("loginPass").value=""; document.getElementById("loginErr").textContent=""; document.getElementById("loginOverlay").classList.remove("hide"); } initLogin();