|
|
@@ -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>}
|