Browse Source

how 表头优化:拆框架(去轻标签)+ 动作标"模型推导" + 创作阶段表头可点看5个定值

- "② 拆框架 + 轻标签" → "② 拆框架"
- 动作列头 → "动作(模型推导)",标明是模型实时抽、非定死
- 创作阶段列头改为可点按钮(▸),弹窗列出写死的 5 个(定向/构思/结构/成文/打磨)+ 含义,并说明与"动作"的区别

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SamLee 4 weeks ago
parent
commit
72fbda7eb0
1 changed files with 23 additions and 6 deletions
  1. 23 6
      web/index.html

+ 23 - 6
web/index.html

@@ -80,6 +80,7 @@
   th.c-scope,td.scope{width:92px;min-width:92px;max-width:92px;word-break:break-word}
   th.g-frame{background:#0e7490;color:#fff}
   th.g-scope{background:#7c3aed;color:#fff}
+  th.cstage-h{cursor:pointer}th.cstage-h:hover{background:#0e7490}
   th.c-idx{background:#475569;color:#fff;vertical-align:middle}
   thead tr:nth-child(2) th.c-intent,thead tr:nth-child(2) th.c-cstage,thead tr:nth-child(2) th.c-act,thead tr:nth-child(2) th.c-dir,thead tr:nth-child(2) th.c-out{background:#0891b2;color:#fff}
   thead tr:nth-child(2) th.s-substance{background:#dc2626;color:#fff}thead tr:nth-child(2) th.s-form{background:#2563eb;color:#fff}
@@ -172,6 +173,18 @@ const j=u=>fetch(u,{cache:"no-store"}).then(r=>r.json());
 const SCOPES=[["substance","实质"],["form","形式"],["feeling","感受"],["effect","作用"],["intent","意图"]];
 const SC_CN={substance:"实质",form:"形式",feeling:"感受",effect:"作用",intent:"意图"};
 const TYPECN={how:"How 工序",what:"What 构成",why:"Why 原理"};
+const CSTAGE_DOC=`## 创作阶段:写死的 5 个(每步选 1 个)
+how 工序每一步命中其中**一个**;不在这 5 个里的值会被代码丢弃(受控词表,不开放)。
+
+| 阶段 | 在干什么 |
+|---|---|
+| **定向** | 定主题 / 方向 / 受众——还没开始具体创作 |
+| **构思** | 生成核心创意 / 钩子 / 角度 / 冲突 |
+| **结构** | 搭骨架 / 大纲 / 顺序 |
+| **成文** | 把结构写成具体文字 / 镜头 |
+| **打磨** | 修改 / 精炼 / 优化 / 定稿 |
+
+(区别于「动作」:动作是模型从帖子里实时抽的、不固定;创作阶段是定死的 5 选 1。)`;
 // 把提示词里的"黑话"形式标签换成大白话(找不到就原样显示)
 const FORM_PLAIN={"取舍":"怎么用","依据":"为什么对","机制":"怎么起作用","平台逻辑":"平台规则","读者心理":"读者心理","例证":"例子","反例":"反例","判据":"判断标准","对照":"对比","清单":"清单","分类":"分类","定义":"定义","维度":"方面"};
 const plainForm=f=>FORM_PLAIN[f]||f;
@@ -276,15 +289,15 @@ function KScopes({list,onScope}){
     {list.map((x,i)=><ScopeChip key={i} x={{...x}} onScope={onScope} showType={true}/>)}</div>;
 }
 
-function HowTable({k,onScope,onPrompt,onSource}){
+function HowTable({k,onScope,onPrompt,onSource,onCstage}){
   const steps=k.steps||[];
   const scOf=(s,t)=>(s.作用域||[]).filter(x=>x.scope_type===t);
   return <div className="twrap"><table className="proc">
     <thead>
       <tr><th className="c-idx" rowSpan="2">#</th>
-        <th className="g-frame" colSpan="5">② 拆框架 + 轻标签</th>
+        <th className="g-frame" colSpan="5">② 拆框架</th>
         <th className="g-scope" colSpan="5">③ 作用域</th></tr>
-      <tr><th className="c-intent">输入</th><th className="c-cstage">创作<br/>阶段</th><th className="c-act">动作</th><th className="c-dir">方法</th><th className="c-out">产出</th>
+      <tr><th className="c-intent">输入</th><th className="c-cstage cstage-h" title="看 5 个写死的创作阶段" onClick={()=>onCstage&&onCstage()}>创作<br/>阶段</th><th className="c-act">动作<br/>(模型推导)</th><th className="c-dir">方法</th><th className="c-out">产出</th>
         {SCOPES.map(([kk,cn])=><th key={kk} className={"c-scope s-"+kk}>{cn}</th>)}</tr>
     </thead>
     <tbody>{steps.map((s,i)=><tr className="step" key={i}>
@@ -323,7 +336,7 @@ function WhyCard({k,onScope}){
   </div>;
 }
 
-function KnowledgeCard({k,idx,onScope,onPrompt,onJson,onSource,payload,how_titles,onGloss}){
+function KnowledgeCard({k,idx,onScope,onPrompt,onJson,onSource,payload,how_titles,onGloss,onCstage}){
   const par=k.parent;
   return <div className="kcard" id={"k-"+k.id}>
     <div className="khead">
@@ -336,7 +349,7 @@ function KnowledgeCard({k,idx,onScope,onPrompt,onJson,onSource,payload,how_title
       <span className="kacts">{payload&&<button className="lbtn" onClick={()=>onJson(payload)}>⚙️ 入库 payload</button>}</span>
     </div>
     <div className="kbody">
-      {k.type==="how"&&<HowTable k={k} onScope={onScope} onPrompt={onPrompt} onSource={onSource}/>}
+      {k.type==="how"&&<HowTable k={k} onScope={onScope} onPrompt={onPrompt} onSource={onSource} onCstage={onCstage}/>}
       {k.type==="what"&&<WhatCard k={k} onScope={onScope} onGloss={onGloss}/>}
       {k.type==="why"&&<WhyCard k={k} onScope={onScope}/>}
     </div>
@@ -353,6 +366,7 @@ function App(){
   const [src,setSrc]=useState(null);
   const [hl,setHl]=useState(false);
   const [gloss,setGloss]=useState(false);
+  const [cstage,setCstage]=useState(false);
   useEffect(()=>{Promise.all([j("/frameworks.json"),j("/payloads.json").catch(()=>[])]).then(([f,pl])=>{
     setItems((f.posts||[]).map(p=>({...p,payloads:(pl||[]).filter(x=>(x.source||{}).id===(p.source_id||("xhs_"+p.post_id)))})));});},[]);
   useEffect(()=>{document.body.classList.toggle("hl",hl);},[hl]);
@@ -396,7 +410,7 @@ function App(){
         <button className={"lbtn"+(hl?" on":"")} onClick={()=>setHl(!hl)}>高亮「新值」</button>
       </div>
       {ks.length===0 && <div className="kcard"><div className="kbody" style={{padding:"20px 16px",color:"#9ca3af",fontSize:"13px"}}>🚫 这帖<b style={{color:"#6b7280"}}>没有可提取的创作知识</b>(纯作品 / 展示 / 无关)——① 读懂时 <code>is_empty=true</code>,后面拆颗/归类/入库已自动跳过。</div></div>}
-      {ks.map((k,i)=><KnowledgeCard key={i} k={k} idx={i} onScope={setScope} onPrompt={openPrompt} onJson={setJson} onSource={openSource} payload={payloadOf(k)} how_titles={how_titles} onGloss={()=>setGloss(true)}/>)}
+      {ks.map((k,i)=><KnowledgeCard key={i} k={k} idx={i} onScope={setScope} onPrompt={openPrompt} onJson={setJson} onSource={openSource} payload={payloadOf(k)} how_titles={how_titles} onGloss={()=>setGloss(true)} onCstage={()=>setCstage(true)}/>)}
     </div>
     {scope&&<div><div className="ov" onClick={()=>setScope(null)}></div>
       <div className="drawer"><h2>作用域回扣详情<span className="x" onClick={()=>setScope(null)}>×</span></h2>
@@ -424,6 +438,9 @@ function App(){
         {c.video_url&&<video src={c.video_url+(c.start!=null?("#t="+Math.floor(c.start)+","+Math.floor(c.end)):"")} controls/>}
         {c.content?<div className="srcread">① 在这张卡读到的:{c.content}</div>:<div style={{color:"#9ca3af",fontSize:"12px",marginTop:5}}>(这张卡没读到要点)</div>}
       </div>)}</div></div></div>}
+    {cstage&&<div className="modal" onClick={()=>setCstage(false)}><div className="mbox" onClick={e=>e.stopPropagation()}>
+      <h2>📐 创作阶段 · 写死的 5 个<span className="x" onClick={()=>setCstage(false)}>×</span></h2>
+      <div className="body"><div className="md" dangerouslySetInnerHTML={{__html:mdToHtml(CSTAGE_DOC)}}/></div></div></div>}
     {gloss&&<div className="modal" onClick={()=>setGloss(false)}><div className="mbox" onClick={e=>e.stopPropagation()}>
       <h2>❓ 名词说明 · 用大白话讲清楚<span className="x" onClick={()=>setGloss(false)}>×</span></h2>
       <div className="body"><div className="md" dangerouslySetInnerHTML={{__html:mdToHtml(GLOSSARY)}}/></div></div></div>}