- grades: 拆分 batch-grade-entry (457→374) + grade-record-list (523→231),新增 4 个子组件 - attendance: 迁移 stats-cards/filters 到 StatsGrid/FilterBar 底座 - error-book: 迁移 stats-cards/filters 到 StatsGrid/FilterBar 底座 - elective: 迁移 stats-cards/filters 到 StatsGrid/FilterBar 底座 - 删除 12 个重复组件,新增 app 层 filter 组件就近放置 - tsc 零错误,lint 无新增错误
252 lines
16 KiB
HTML
252 lines
16 KiB
HTML
<h2>正文占位符标记布局</h2>
|
||
<p class="subtitle">正文中嵌入占位符标记(特殊符号),默认接近透明,选中节点时完整显示</p>
|
||
|
||
<div class="mockup">
|
||
<div class="mockup-header">备课编辑器 — 默认状态(占位符 10% 透明度)</div>
|
||
<div class="mockup-body" style="padding:0;background:#f1f5f9;overflow:hidden;">
|
||
<div style="font-family:monospace;font-size:12px;line-height:1.6;position:relative;height:560px;">
|
||
|
||
<!-- 顶部工具栏 -->
|
||
<div style="background:#1e293b;color:#e2e8f0;padding:8px 12px;display:flex;justify-content:space-between;align-items:center;z-index:10;position:relative;">
|
||
<div style="display:flex;align-items:center;gap:8px;">
|
||
<span>📖</span>
|
||
<span style="font-weight:bold;">秋天(第一课时)</span>
|
||
<span style="background:#334155;padding:2px 8px;border-radius:3px;font-size:10px;">语文 · 一年级上册</span>
|
||
</div>
|
||
<div style="display:flex;align-items:center;gap:8px;">
|
||
<span style="font-size:10px;color:#94a3b8;">💾 已保存</span>
|
||
<span style="background:#3b82f6;padding:4px 12px;border-radius:3px;font-size:10px;">💾 保存</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 画布区域 -->
|
||
<div style="position:relative;width:100%;height:520px;background:#f1f5f9;background-image:radial-gradient(#cbd5e1 1px, transparent 1px);background-size:20px 20px;overflow:hidden;">
|
||
|
||
<!-- SVG 连线层(默认 10% 透明度) -->
|
||
<svg style="position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;opacity:0.1;" viewBox="0 0 800 520">
|
||
<path d="M 130 120 Q 200 140 290 175" stroke="#3b82f6" stroke-width="2" fill="none" stroke-dasharray="4 4"/>
|
||
<path d="M 130 220 Q 200 230 290 215" stroke="#f59e0b" stroke-width="2" fill="none" stroke-dasharray="4 4"/>
|
||
<path d="M 670 120 Q 600 150 510 195" stroke="#0ea5e9" stroke-width="2" fill="none" stroke-dasharray="4 4"/>
|
||
<path d="M 670 220 Q 600 240 510 235" stroke="#ec4899" stroke-width="2" fill="none" stroke-dasharray="4 4"/>
|
||
<path d="M 670 340 Q 600 320 510 275" stroke="#22c55e" stroke-width="2" fill="none" stroke-dasharray="4 4"/>
|
||
</svg>
|
||
|
||
<!-- 中央:正文容器(不可移动) -->
|
||
<div style="position:absolute;left:280px;top:60px;width:240px;background:#fffbeb;border:2px solid #f59e0b;border-radius:8px;padding:12px;box-shadow:0 4px 12px rgba(0,0,0,0.1);">
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;border-bottom:1px solid #fde68a;padding-bottom:6px;">
|
||
<span style="font-size:11px;font-weight:bold;color:#92400e;">📜 课文正文</span>
|
||
<span style="font-size:9px;color:#94a3b8;background:#fef3c7;padding:1px 4px;border-radius:2px;">🔒 固定</span>
|
||
</div>
|
||
<div style="font-size:13px;color:#78350f;line-height:2;">
|
||
<div style="text-align:center;font-weight:bold;margin-bottom:6px;">秋天</div>
|
||
<p style="margin:0 0 6px 0;">
|
||
<!-- 占位符 1(导入节点)- 默认 10% 透明度 -->
|
||
<span style="display:inline-block;background:#3b82f6;color:#fff;border-radius:3px;padding:0 4px;font-size:9px;font-weight:bold;opacity:0.1;margin-right:2px;">①</span>天气凉了,树叶黄了,
|
||
</p>
|
||
<p style="margin:0 0 6px 0;">
|
||
<!-- 占位符 2(文本研习)- 默认 10% 透明度 -->
|
||
<span style="display:inline-block;background:#f59e0b;color:#fff;border-radius:3px;padding:0 4px;font-size:9px;font-weight:bold;opacity:0.1;margin-right:2px;">②</span>天空那么蓝,那么高。
|
||
</p>
|
||
<p style="margin:0 0 6px 0;">
|
||
一群大雁往南飞,
|
||
</p>
|
||
<p style="margin:0 0 6px 0;">
|
||
一会儿排成个"人"字<span style="display:inline-block;background:#0ea5e9;color:#fff;border-radius:3px;padding:0 4px;font-size:9px;font-weight:bold;opacity:0.1;margin-left:2px;">③</span>,
|
||
</p>
|
||
<p style="margin:0 0 6px 0;">
|
||
一会儿排成个"一"字<span style="display:inline-block;background:#ec4899;color:#fff;border-radius:3px;padding:0 4px;font-size:9px;font-weight:bold;opacity:0.1;margin-left:2px;">④</span>。
|
||
</p>
|
||
<p style="margin:0;">
|
||
<span style="display:inline-block;background:#22c55e;color:#fff;border-radius:3px;padding:0 4px;font-size:9px;font-weight:bold;opacity:0.1;margin-right:2px;">⑤</span>啊!秋天来了!
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 左侧节点 -->
|
||
<div style="position:absolute;left:30px;top:90px;width:140px;background:#fff;border:1px solid #3b82f6;border-left:3px solid #3b82f6;border-radius:6px;padding:8px;box-shadow:0 2px 6px rgba(0,0,0,0.08);">
|
||
<div style="display:flex;align-items:center;gap:4px;margin-bottom:4px;">
|
||
<span style="background:#3b82f6;color:#fff;border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;font-size:8px;font-weight:bold;">1</span>
|
||
<span style="font-size:10px;font-weight:bold;color:#1e3a8a;">💡 导入</span>
|
||
</div>
|
||
<div style="font-size:9px;color:#64748b;">提问:你见过秋天的树叶吗?</div>
|
||
</div>
|
||
|
||
<div style="position:absolute;left:30px;top:200px;width:140px;background:#fff;border:1px solid #f59e0b;border-left:3px solid #f59e0b;border-radius:6px;padding:8px;box-shadow:0 2px 6px rgba(0,0,0,0.08);">
|
||
<div style="display:flex;align-items:center;gap:4px;margin-bottom:4px;">
|
||
<span style="background:#f59e0b;color:#fff;border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;font-size:8px;font-weight:bold;">2</span>
|
||
<span style="font-size:10px;font-weight:bold;color:#92400e;">📝 文本研习</span>
|
||
</div>
|
||
<div style="font-size:9px;color:#64748b;">赏析:叠词的运用</div>
|
||
</div>
|
||
|
||
<!-- 右侧节点 -->
|
||
<div style="position:absolute;left:630px;top:90px;width:140px;background:#fff;border:1px solid #0ea5e9;border-left:3px solid #0ea5e9;border-radius:6px;padding:8px;box-shadow:0 2px 6px rgba(0,0,0,0.08);">
|
||
<div style="display:flex;align-items:center;gap:4px;margin-bottom:4px;">
|
||
<span style="background:#0ea5e9;color:#fff;border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;font-size:8px;font-weight:bold;">3</span>
|
||
<span style="font-size:10px;font-weight:bold;color:#075985;">📚 新授</span>
|
||
</div>
|
||
<div style="font-size:9px;color:#64748b;">讲解:大雁南飞</div>
|
||
</div>
|
||
|
||
<div style="position:absolute;left:630px;top:200px;width:140px;background:#fff;border:1px solid #ec4899;border-left:3px solid #ec4899;border-radius:6px;padding:8px;box-shadow:0 2px 6px rgba(0,0,0,0.08);">
|
||
<div style="display:flex;align-items:center;gap:4px;margin-bottom:4px;">
|
||
<span style="background:#ec4899;color:#fff;border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;font-size:8px;font-weight:bold;">4</span>
|
||
<span style="font-size:10px;font-weight:bold;color:#9f1239;">✏️ 练习</span>
|
||
</div>
|
||
<div style="font-size:9px;color:#64748b;">3 道题</div>
|
||
</div>
|
||
|
||
<div style="position:absolute;left:630px;top:320px;width:140px;background:#fff;border:1px solid #22c55e;border-left:3px solid #22c55e;border-radius:6px;padding:8px;box-shadow:0 2px 6px rgba(0,0,0,0.08);">
|
||
<div style="display:flex;align-items:center;gap:4px;margin-bottom:4px;">
|
||
<span style="background:#22c55e;color:#fff;border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;font-size:8px;font-weight:bold;">5</span>
|
||
<span style="font-size:10px;font-weight:bold;color:#166534;">📌 小结</span>
|
||
</div>
|
||
<div style="font-size:9px;color:#64748b;">总结全文</div>
|
||
</div>
|
||
|
||
<div style="position:absolute;top:12px;right:12px;background:#fff;border:1px solid #e2e8f0;border-radius:4px;padding:4px 8px;font-size:9px;color:#64748b;">
|
||
占位符默认 10% · 选中节点时 100% 显示
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 选中状态对比 -->
|
||
<div class="section" style="margin-top:24px;">
|
||
<h3>选中"导入"节点时的状态变化</h3>
|
||
<div class="split">
|
||
<div class="mockup">
|
||
<div class="mockup-header">默认 — 占位符 ① 10% 透明度</div>
|
||
<div class="mockup-body" style="padding:16px;background:#fffbeb;">
|
||
<div style="font-size:14px;color:#78350f;line-height:2;font-family:serif;">
|
||
<span style="display:inline-block;background:#3b82f6;color:#fff;border-radius:3px;padding:0 5px;font-size:10px;font-weight:bold;opacity:0.1;margin-right:3px;">①</span>天气凉了,树叶黄了,
|
||
</div>
|
||
<div style="margin-top:12px;font-size:10px;color:#94a3b8;text-align:center;">
|
||
占位符几乎不可见 · 画布干净
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="mockup">
|
||
<div class="mockup-header">选中"导入"节点 — 占位符 ① 100% + 连线显示</div>
|
||
<div class="mockup-body" style="padding:16px;background:#fffbeb;">
|
||
<div style="font-size:14px;color:#78350f;line-height:2;font-family:serif;">
|
||
<span style="display:inline-block;background:#3b82f6;color:#fff;border-radius:3px;padding:0 5px;font-size:10px;font-weight:bold;opacity:1;margin-right:3px;box-shadow:0 0 0 2px #3b82f633;">①</span>天气凉了,树叶黄了,
|
||
</div>
|
||
<div style="margin-top:12px;font-size:10px;color:#3b82f6;text-align:center;">
|
||
占位符完整显示 · 连线高亮 · 锚定位置清晰
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 占位符样式选项 -->
|
||
<div class="section">
|
||
<h3>占位符样式选项</h3>
|
||
<p class="subtitle">选择占位符在正文中的视觉呈现方式</p>
|
||
<div class="cards" data-multiselect>
|
||
<div class="card" data-choice="number" onclick="toggleSelect(this)">
|
||
<div class="card-image" style="padding:20px;background:#fffbeb;text-align:center;">
|
||
<div style="font-size:16px;color:#78350f;font-family:serif;line-height:2;">
|
||
<span style="display:inline-block;background:#3b82f6;color:#fff;border-radius:3px;padding:0 6px;font-size:11px;font-weight:bold;">①</span>天气凉了
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<h3>数字圆圈</h3>
|
||
<p>①②③④⑤ — 与节点编号对应,简洁清晰</p>
|
||
</div>
|
||
</div>
|
||
<div class="card" data-choice="icon" onclick="toggleSelect(this)">
|
||
<div class="card-image" style="padding:20px;background:#fffbeb;text-align:center;">
|
||
<div style="font-size:16px;color:#78350f;font-family:serif;line-height:2;">
|
||
<span style="display:inline-block;background:#3b82f6;color:#fff;border-radius:3px;padding:1px 5px;font-size:11px;">💡</span>天气凉了
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<h3>节点图标</h3>
|
||
<p>💡📝📚✏️📌 — 与节点类型图标一致,直观</p>
|
||
</div>
|
||
</div>
|
||
<div class="card" data-choice="dot" onclick="toggleSelect(this)">
|
||
<div class="card-image" style="padding:20px;background:#fffbeb;text-align:center;">
|
||
<div style="font-size:16px;color:#78350f;font-family:serif;line-height:2;">
|
||
<span style="display:inline-block;background:#3b82f6;color:#fff;border-radius:50%;width:10px;height:10px;font-size:8px;text-align:center;line-height:10px;">●</span>天气凉了
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<h3>彩色圆点</h3>
|
||
<p>● — 极简,颜色对应节点,不干扰阅读</p>
|
||
</div>
|
||
</div>
|
||
<div class="card" data-choice="bracket" onclick="toggleSelect(this)">
|
||
<div class="card-image" style="padding:20px;background:#fffbeb;text-align:center;">
|
||
<div style="font-size:16px;color:#78350f;font-family:serif;line-height:2;">
|
||
<span style="color:#3b82f6;font-weight:bold;">【1】</span>天气凉了
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<h3>方括号编号</h3>
|
||
<p>【1】【2】【3】— 类似脚注标记,学术感</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 数据模型更新 -->
|
||
<div class="section">
|
||
<h3>占位符数据模型</h3>
|
||
<div style="background:#1e293b;color:#e2e8f0;padding:16px;border-radius:6px;font-family:monospace;font-size:11px;line-height:1.6;">
|
||
<div style="color:#94a3b8;">// 正文中的占位符标记</div>
|
||
<div><span style="color:#f59e0b;">interface</span> <span style="color:#3b82f6;">ContentPlaceholder</span> {</div>
|
||
<div> id: <span style="color:#10b981;">string</span>; <span style="color:#64748b;">// 占位符 ID</span></div>
|
||
<div> nodeId: <span style="color:#10b981;">string</span>; <span style="color:#64748b;">// 关联的节点 ID</span></div>
|
||
<div> offset: <span style="color:#10b981;">number</span>; <span style="color:#64748b;">// 在正文纯文本中的字符偏移量</span></div>
|
||
<div> label: <span style="color:#10b981;">string</span>; <span style="color:#64748b;">// 显示的标记("①" / "💡" / "●" / "【1】")</span></div>
|
||
<div> color: <span style="color:#10b981;">string</span>; <span style="color:#64748b;">// 节点颜色(用于占位符背景)</span></div>
|
||
<div>}</div>
|
||
<br>
|
||
<div style="color:#94a3b8;">// 正文渲染时注入占位符</div>
|
||
<div><span style="color:#f59e0b;">function</span> <span style="color:#3b82f6;">renderContentWithPlaceholders</span>(</div>
|
||
<div> content: <span style="color:#10b981;">string</span>, <span style="color:#64748b;">// Markdown 原文</span></div>
|
||
<div> placeholders: <span style="color:#3b82f6;">ContentPlaceholder</span>[]</div>
|
||
<div>): <span style="color:#10b981;">string</span> {</div>
|
||
<div> <span style="color:#64748b;">// 按 offset 排序,在对应位置插入占位符标记</span></div>
|
||
<div> <span style="color:#64748b;">// 渲染为 <span class="placeholder" data-node-id="xxx">①</span></span></div>
|
||
<div>}</div>
|
||
<br>
|
||
<div style="color:#94a3b8;">// CSS 透明度控制</div>
|
||
<div>.placeholder { <span style="color:#10b981;">opacity</span>: <span style="color:#f59e0b;">0.1</span>; <span style="color:#10b981;">transition</span>: <span style="color:#f59e0b;">opacity 0.2s</span>; }</div>
|
||
<div>.placeholder.active { <span style="color:#10b981;">opacity</span>: <span style="color:#f59e0b;">1</span>; }</div>
|
||
<div>.placeholder:hover { <span style="color:#10b981;">opacity</span>: <span style="color:#f59e0b;">0.6</span>; }</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h3>交互流程</h3>
|
||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
|
||
<div style="background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:12px;">
|
||
<h4 style="margin:0 0 8px 0;color:#3b82f6;">🔗 添加占位符</h4>
|
||
<ol style="margin:0;padding-left:16px;font-size:11px;color:#475569;line-height:1.8;">
|
||
<li>教师点击正文某个位置(光标位置)</li>
|
||
<li>或选中一段文字后释放</li>
|
||
<li>弹出菜单:"在此处添加节点 →"</li>
|
||
<li>选择节点类型或已有节点</li>
|
||
<li>在正文对应位置插入占位符标记</li>
|
||
<li>创建 AnchorEdge 连线</li>
|
||
</ol>
|
||
</div>
|
||
<div style="background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:12px;">
|
||
<h4 style="margin:0 0 8px 0;color:#22c55e;">👁️ 选中节点时的视觉反馈</h4>
|
||
<ol style="margin:0;padding-left:16px;font-size:11px;color:#475569;line-height:1.8;">
|
||
<li>点击画布上的某个节点</li>
|
||
<li>该节点对应的占位符 opacity 从 0.1 → 1</li>
|
||
<li>连线从 10% → 100% 显示</li>
|
||
<li>占位符添加 active 样式(边框/阴影)</li>
|
||
<li>其他占位符保持 10% 透明度</li>
|
||
<li>点击空白处恢复默认状态</li>
|
||
</ol>
|
||
</div>
|
||
</div>
|
||
</div>
|