feat(ai-protocols): add MCP and A2A protocol demos and documentation

docs(ai-protocols): update AI protocols page with visual demos and detailed explanations
style(git-demos): improve responsive design and layout for git visualization components
refactor(ai-history): simplify and clean up demo components
chore: update config to register new AI protocol components
This commit is contained in:
sanbuphy
2026-02-22 18:26:19 +08:00
parent 4b83a4c23e
commit e5a5b9df5b
31 changed files with 5093 additions and 5333 deletions
@@ -2,69 +2,75 @@
<div class="adder-demo">
<div class="demo-header">
<span class="title">加法器用逻辑门做二进制加法</span>
<span class="subtitle">点击蓝色位按钮切换 0/1观察进位如何逐位传递</span>
<span class="subtitle">就像手算竖式从个位往高位算逢二进一进位往左传</span>
</div>
<!-- 名词解释 -->
<div class="legend">
<span class="legend-item"><span class="dot a" />A = 被加数</span>
<span class="legend-item"><span class="dot b" />B = 加数</span>
<span class="legend-item"><span class="dot s" />S = Sum本位结果</span>
<span class="legend-item"><span class="dot c" />C = 进位Carry传给下一位</span>
</div>
<!-- 输入控制 -->
<div class="control-panel">
<div class="input-group">
<span class="group-label">A被加数</span>
<div class="bits">
<button
v-for="(bit, i) in bitsA"
:key="'a' + i"
class="bit-btn"
:class="{ on: bit }"
@click="toggleBit('A', i)"
>
{{ bit }}
</button>
</div>
<span class="decimal">= {{ decimalA }}</span>
<label>
<span class="control-label">A被加数</span>
<input v-model.number="inputA" type="number" min="0" max="15" class="num-input" />
</label>
<span class="op">+</span>
<label>
<span class="control-label">B加数</span>
<input v-model.number="inputB" type="number" min="0" max="15" class="num-input" />
</label>
<span class="eq">=</span>
<span class="result-dec">{{ resultDec }}</span>
</div>
<div class="why-what-box">
<p class="why-p">
<strong>为啥要看这些</strong>CPU 只会处理 0 1所以加法要一位一位每一列 0 1 都需要一个小电路来算这一位写几要不要往左进位
</p>
<p class="what-p">
<strong>这些词是啥</strong>
<span class="term">半加器</span>只算这一位的 A+B最右边没有进位进来
<span class="term">全加器</span> A+B+上一位的进位
<span class="term">S</span>这一位写下的数字0 1
<span class="term">Cout</span>要不要往左边一位进 1进就是 1不进就是 0
</p>
</div>
<div class="example-block">
<div class="example-row">
<span class="example-label">A被加数</span>
<span class="example-bits">
<span v-for="(b, i) in bitsA" :key="'a'+i" class="bit" :class="{ active: highlightedBit === (3 - i) }">{{ b }}</span>
</span>
<span class="example-dec">= {{ inputA }}</span>
</div>
<div class="op-sign">+</div>
<div class="input-group">
<span class="group-label">B加数</span>
<div class="bits">
<button
v-for="(bit, i) in bitsB"
:key="'b' + i"
class="bit-btn"
:class="{ on: bit }"
@click="toggleBit('B', i)"
>
{{ bit }}
</button>
</div>
<span class="decimal">= {{ decimalB }}</span>
<div class="example-row">
<span class="example-label">B加数</span>
<span class="example-bits">
<span v-for="(b, i) in bitsB" :key="'b'+i" class="bit" :class="{ active: highlightedBit === (3 - i) }">{{ b }}</span>
</span>
<span class="example-dec">= {{ inputB }}</span>
</div>
<div class="op-sign">=</div>
<div class="result-inline">
<span class="result-bin">{{ resultBinary }}</span>
<span class="result-dec">十进制 {{ resultDecimal }}</span>
<div class="example-row result-row">
<span class="example-label">结果</span>
<span class="example-bits">
<span v-for="(b, i) in bitsSum" :key="'s'+i" class="bit" :class="{ active: highlightedBit === (3 - i) }">{{ b }}</span>
</span>
<span class="example-dec">= {{ resultDec }}</span>
</div>
<div class="bit-legend">
<span v-for="i in 4" :key="i" class="bit-legend-item">{{ 4 - i }}</span>
</div>
</div>
<!-- 每位加法器展示 -->
<div class="stages-label">逐位计算过程从最低位开始</div>
<div class="stages-label">逐位计算从右往左 0 3 对应上面每一列</div>
<div class="adder-stages">
<div
v-for="(stage, idx) in stageData"
v-for="(stage, idx) in stages"
:key="idx"
class="stage"
:class="{ 'stage-highlight': highlightedBit === stage.bitPos }"
@mouseenter="highlightedBit = stage.bitPos"
@mouseleave="highlightedBit = null"
>
<div class="stage-title"> {{ stage.bitPos }} {{ stage.posName }}</div>
<div class="stage-content">
<!-- 输入列 -->
<div class="io-col inputs-col">
<div class="io-row">
<span class="io-badge a-badge">A</span>
@@ -74,55 +80,34 @@
<span class="io-badge b-badge">B</span>
<span class="io-val">{{ stage.b }}</span>
</div>
<div v-if="stage.carryIn !== null" class="io-row carry-in-row">
<div v-if="stage.carryIn !== null" class="io-row">
<span class="io-badge cin-badge">Cin</span>
<span class="io-val">{{ stage.carryIn }}</span>
</div>
</div>
<!-- 全加器框 -->
<div class="fa-box">
<div class="fa-label">{{ stage.carryIn !== null ? '全加器' : '半加器' }}</div>
<div class="fa-hint">{{ stage.carryIn !== null ? 'Full Adder' : 'Half Adder' }}</div>
<div class="fa-hint">{{ stage.carryIn !== null ? 'A+B+进位' : '只算 A+B' }}</div>
</div>
<!-- 输出列 -->
<div class="io-col outputs-col">
<div class="io-row">
<span class="io-badge s-badge">S</span>
<span class="io-badge s-badge" :title="'S = 这一位写下的数'">S</span>
<span class="io-val sum-val">{{ stage.sum }}</span>
</div>
<div class="io-row">
<span class="io-badge cout-badge">Cout</span>
<span class="io-badge cout-badge" :title="'Cout = 往左进 0 还是 1'">Cout</span>
<span class="io-val carry-val">{{ stage.carryOut }}</span>
</div>
</div>
</div>
<!-- 进位传递提示 -->
<div v-if="idx < stageData.length - 1 && stage.carryOut" class="carry-hint">
进位 {{ stage.carryOut }} 传给第 {{ stage.bitPos + 1 }}
<div v-if="idx < stages.length - 1" class="carry-hint" :class="{ 'no-carry': !stage.carryOut }">
{{ stage.carryOut ? `进位 ${stage.carryOut} 传给第 ${stage.bitPos + 1} ` : '无进位' }}
</div>
<div v-else-if="idx < stageData.length - 1" class="carry-hint no-carry">
无进位
</div>
</div>
</div>
<!-- 结果 -->
<div class="result-bar">
<div class="result-row">
<span class="result-label">二进制结果</span>
<span class="result-bits">{{ resultBinary }}</span>
</div>
<div class="result-row">
<span class="result-label">十进制验证</span>
<span class="result-eq">{{ decimalA }} + {{ decimalB }} = {{ resultDecimal }}</span>
</div>
</div>
<div class="info-box">
<strong>核心思想</strong>每位全加器接收 AB 和上一位的进位Cin输出本位的和S向上传递的进位Cout我们手算竖式加法"逢二进一"完全一致
<strong>核心思想</strong>每位全加器接收 AB 和上一位的进位Cin输出本位的和S传给下一位的进位Cout和手算竖式逢二进一一致
</div>
</div>
</template>
@@ -130,57 +115,66 @@
<script setup>
import { ref, computed } from 'vue'
const bitsA = ref([0, 0, 1, 1])
const bitsB = ref([0, 0, 1, 0])
const POS_NAMES = ['最低位', '次低位', '次高位', '最高位']
const toggleBit = (arr, i) => {
if (arr === 'A') {
bitsA.value[i] = bitsA.value[i] ? 0 : 1
} else {
bitsB.value[i] = bitsB.value[i] ? 0 : 1
}
function clamp(n) {
const v = Number(n)
if (Number.isNaN(v)) return 0
return Math.max(0, Math.min(15, Math.floor(v)))
}
const decimalA = computed(() =>
bitsA.value.reduce((acc, bit, i) => acc + bit * Math.pow(2, 3 - i), 0)
)
const inputA = ref(3)
const inputB = ref(2)
const highlightedBit = ref(null)
const decimalB = computed(() =>
bitsB.value.reduce((acc, bit, i) => acc + bit * Math.pow(2, 3 - i), 0)
)
const clampedA = computed(() => clamp(inputA.value))
const clampedB = computed(() => clamp(inputB.value))
const stageData = computed(() => {
const stages = []
let carry = 0
const posNames = ['最低位', '次低位', '次高位', '最高位']
for (let i = 3; i >= 0; i--) {
const a = bitsA.value[i]
const b = bitsB.value[i]
const total = a + b + carry
const sum = total % 2
const carryOut = total >= 2 ? 1 : 0
stages.push({
bitPos: 3 - i,
posName: posNames[3 - i],
const bitsA = computed(() => (clampedA.value >>> 0).toString(2).padStart(4, '0').split(''))
const bitsB = computed(() => (clampedB.value >>> 0).toString(2).padStart(4, '0').split(''))
const stages = computed(() => {
const A = clampedA.value
const B = clampedB.value
const result = []
let carryIn = null
for (let i = 0; i < 4; i++) {
const a = (A >> i) & 1
const b = (B >> i) & 1
let sum, carryOut
if (carryIn === null) {
sum = a ^ b
carryOut = a & b
} else {
sum = (a ^ b) ^ carryIn
carryOut = (a & b) | (carryIn & (a ^ b))
}
result.push({
bitPos: i,
posName: POS_NAMES[i],
a,
b,
carryIn: stages.length > 0 ? carry : null,
carryIn: carryIn === null ? null : carryIn,
sum,
carryOut
})
carry = carryOut
carryIn = carryOut
}
return stages
return result
})
const sumBits = computed(() => stageData.value.map((s) => s.sum).reverse())
const resultBinary = computed(() => {
const lastCarry = stageData.value[stageData.value.length - 1]?.carryOut || 0
return (lastCarry ? lastCarry.toString() : '') + sumBits.value.join('')
const bitsSum = computed(() => {
const S = stages.value.reduce((acc, s, i) => acc + (s.sum << i), 0)
return (S >>> 0).toString(2).padStart(4, '0').split('')
})
const resultDecimal = computed(() => decimalA.value + decimalB.value)
const fourBitResult = computed(() =>
stages.value.reduce((acc, s, i) => acc + (s.sum << i), 0)
)
const overflow = computed(() => clampedA.value + clampedB.value > 15)
const resultDec = computed(() =>
overflow.value ? `${fourBitResult.value}4 位溢出)` : String(fourBitResult.value)
)
</script>
<style scoped>
@@ -193,147 +187,167 @@ const resultDecimal = computed(() => decimalA.value + decimalB.value)
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.65rem;
flex-wrap: wrap;
margin-bottom: 0.35rem;
}
.demo-header .title {
display: block;
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
display: block;
font-size: 0.82rem;
margin-left: 0.5rem;
}
/* 名词解释 */
.legend {
display: flex;
gap: 0.8rem;
flex-wrap: wrap;
margin-bottom: 0.7rem;
font-size: 0.78rem;
color: var(--vp-c-text-2);
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
padding: 0.5rem 0.7rem;
font-weight: normal;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.3rem;
}
.dot {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
}
.dot.a { background: var(--vp-c-brand); }
.dot.b { background: #8b5cf6; }
.dot.s { background: var(--vp-c-success, #16a34a); }
.dot.c { background: #d97706; }
/* 控制面板 */
.control-panel {
display: flex;
align-items: center;
gap: 0.6rem;
padding: 0.55rem 0.75rem;
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg);
margin-bottom: 0.75rem;
flex-wrap: wrap;
}
.input-group {
display: flex;
align-items: center;
gap: 0.4rem;
gap: 0.5rem;
margin-bottom: 0.75rem;
padding: 0.5rem 0;
}
.group-label {
font-size: 0.8rem;
.control-panel label {
display: inline-flex;
align-items: center;
gap: 0.35rem;
}
.control-label {
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.num-input {
width: 3rem;
padding: 0.25rem 0.35rem;
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
font-size: 0.9rem;
background: var(--vp-c-bg);
}
.control-panel .op,
.control-panel .eq {
font-weight: bold;
color: var(--vp-c-text-2);
white-space: nowrap;
}
.bits {
display: flex;
gap: 0.2rem;
}
.bit-btn {
width: 26px;
height: 26px;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg-alt);
border-radius: 4px;
cursor: pointer;
font-size: 0.85rem;
.control-panel .result-dec {
font-weight: bold;
transition: all 0.2s;
color: var(--vp-c-brand-1);
}
.bit-btn.on {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
.why-what-box {
background: var(--vp-c-bg-alt);
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
padding: 0.65rem 0.85rem;
margin-bottom: 0.75rem;
font-size: 0.85rem;
color: var(--vp-c-text-2);
line-height: 1.55;
}
.decimal {
font-size: 0.82rem;
.why-what-box .why-p {
margin: 0 0 0.4rem;
}
.why-what-box .what-p {
margin: 0;
}
.why-what-box .term {
font-weight: 600;
color: var(--vp-c-text-1);
}
.example-block {
margin-bottom: 0.25rem;
}
.bit-legend {
display: flex;
gap: 0.25rem;
margin-left: 6rem;
margin-top: 0.2rem;
font-size: 0.7rem;
color: var(--vp-c-text-3);
}
.bit-legend-item {
min-width: 1.2em;
text-align: center;
}
.example-row .example-bits {
display: flex;
gap: 0.25rem;
}
.bit {
display: inline-block;
min-width: 1.2em;
text-align: center;
padding: 0.1rem 0;
border-radius: 3px;
transition: background 0.15s ease;
}
.bit.active {
background: var(--vp-c-brand-2);
color: var(--vp-c-bg);
}
.stage.stage-highlight {
outline: 2px solid var(--vp-c-brand-1);
outline-offset: 1px;
}
.example-row {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.25rem;
font-size: 0.9rem;
}
.example-label {
color: var(--vp-c-text-2);
min-width: 6rem;
}
.example-bits {
font-family: monospace;
font-variant-numeric: tabular-nums;
}
.example-dec {
color: var(--vp-c-text-2);
font-variant-numeric: tabular-nums;
}
.op-sign {
font-size: 1.1rem;
.result-row .example-bits {
font-weight: bold;
color: var(--vp-c-brand);
flex-shrink: 0;
color: var(--vp-c-brand-1);
}
.result-inline {
display: flex;
align-items: center;
gap: 0.3rem;
}
.result-bin {
font-family: monospace;
font-weight: bold;
color: var(--vp-c-brand);
}
.result-dec {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
/* 阶段 */
.stages-label {
font-size: 0.82rem;
font-size: 0.85rem;
font-weight: bold;
margin-bottom: 0.4rem;
margin: 0.75rem 0 0.4rem;
color: var(--vp-c-text-2);
}
.adder-stages {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.45rem;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
@@ -344,7 +358,7 @@ const resultDecimal = computed(() => decimalA.value + decimalB.value)
padding: 0.55rem;
display: flex;
flex-direction: column;
gap: 0.4rem;
gap: 0.35rem;
}
.stage-title {
@@ -401,16 +415,11 @@ const resultDecimal = computed(() => decimalA.value + decimalB.value)
.sum-val { color: var(--vp-c-success, #16a34a); }
.carry-val { color: #d97706; }
/* 全加器盒子 */
.fa-box {
background: var(--vp-c-bg-alt);
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
padding: 0.3rem 0.35rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.1rem;
flex-shrink: 0;
}
@@ -422,9 +431,9 @@ const resultDecimal = computed(() => decimalA.value + decimalB.value)
.fa-hint {
font-size: 0.6rem;
color: var(--vp-c-text-3);
margin-top: 0.1rem;
}
/* 进位提示 */
.carry-hint {
font-size: 0.65rem;
color: #d97706;
@@ -436,48 +445,14 @@ const resultDecimal = computed(() => decimalA.value + decimalB.value)
color: var(--vp-c-text-3);
}
/* 结果栏 */
.result-bar {
background: var(--vp-c-bg-alt);
border-radius: 6px;
padding: 0.55rem 0.75rem;
display: flex;
gap: 1.5rem;
flex-wrap: wrap;
margin-bottom: 0.75rem;
}
.result-row {
display: flex;
gap: 0.4rem;
align-items: center;
}
.result-label {
font-size: 0.82rem;
color: var(--vp-c-text-2);
}
.result-bits {
font-family: monospace;
font-weight: bold;
color: var(--vp-c-brand);
}
.result-eq {
font-weight: bold;
color: var(--vp-c-success, #16a34a);
}
/* info box */
.info-box {
display: flex;
gap: 0.25rem;
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
display: flex;
gap: 0.25rem;
}
.info-box strong {
@@ -2,48 +2,13 @@
<div class="logic-gate-demo">
<div class="demo-header">
<span class="title">逻辑门用开关做运算</span>
<span class="subtitle">切换输入 A / B同屏观察四种门的输出</span>
</div>
<div class="control-panel">
<span class="panel-hint">点按钮切换 0 / 1右侧四个门同步更新</span>
<div class="input-item">
<span class="input-label">输入 A</span>
<button class="input-btn" :class="{ on: inputA }" @click="inputA = !inputA">
{{ inputA ? '1' : '0' }}
</button>
</div>
<div class="input-item">
<span class="input-label">输入 B</span>
<button class="input-btn" :class="{ on: inputB }" @click="inputB = !inputB">
{{ inputB ? '1' : '0' }}
</button>
</div>
<span class="current-state">当前A={{ inputA ? 1 : 0 }}B={{ inputB ? 1 : 0 }}</span>
</div>
<div class="gate-grid">
<div v-for="gate in gates" :key="gate.name" class="gate-card">
<div class="gate-top">
<span class="gate-name">{{ gate.name }}</span>
<span class="gate-formula">{{ gate.formula }}</span>
</div>
<div class="gate-analogy">{{ gate.analogy }}</div>
<div class="gate-output-row">
<span class="output-label">输出</span>
<span
class="output-value"
:class="{ on: gateOutput(gate.name, inputA, inputB) }"
>
{{ gateOutput(gate.name, inputA, inputB) }}
</span>
<span class="output-hint">{{ gateOutput(gate.name, inputA, inputB) ? '(真 / 导通)' : '(假 / 断开)' }}</span>
</div>
</div>
</div>
<p class="intro">
输入 AB 只能是 0 1四种门按不同规则输出一个 0 1下面表格列出所有 4 种输入组合的结果
</p>
<div class="truth-section">
<div class="table-title">四种门真值表对照高亮行 = 当前输入</div>
<table>
<thead>
<tr>
@@ -56,65 +21,37 @@
</tr>
</thead>
<tbody>
<tr
v-for="row in truthRows"
:key="`${row.a}-${row.b}`"
:class="{
highlight:
row.a === (inputA ? 1 : 0) && row.b === (inputB ? 1 : 0)
}"
>
<tr v-for="row in truthRows" :key="`${row.a}-${row.b}`">
<td>{{ row.a }}</td>
<td>{{ row.b }}</td>
<td>{{ gateOutput('AND', !!row.a, !!row.b) }}</td>
<td>{{ gateOutput('OR', !!row.a, !!row.b) }}</td>
<td>{{ gateOutput('NOT', !!row.a, !!row.b) }}</td>
<td>{{ gateOutput('XOR', !!row.a, !!row.b) }}</td>
<td>{{ row.and }}</td>
<td>{{ row.or }}</td>
<td>{{ row.not }}</td>
<td>{{ row.xor }}</td>
</tr>
</tbody>
</table>
<ul class="col-meaning">
<li><strong>AND</strong>两个都是 1 才输出 1像串联都通才通</li>
<li><strong>OR</strong>有一个 1 就输出 1像并联一通就通</li>
<li><strong>NOT(A)</strong> A 取反0110</li>
<li><strong>XOR</strong>两个不同输出 1相同输出 0</li>
</ul>
</div>
<div class="info-box">
<strong>核心思想</strong>逻辑门用晶体管的"开关"组合实现基本运算AND 像串联OR 像并联NOT 取反XOR 判异所有复杂计算都由这四种基础操作构建而来
<strong>核心思想</strong>逻辑门用晶体管的开关组合实现这四种运算复杂计算都由它们组合而成
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const inputA = ref(false)
const inputB = ref(false)
const gates = [
{ name: 'AND', formula: 'A && B', analogy: '串联:都为 1 才输出 1' },
{ name: 'OR', formula: 'A || B', analogy: '并联:任一为 1 就输出 1' },
{ name: 'NOT', formula: '!A', analogy: '取反:0→11→0' },
{ name: 'XOR', formula: 'A ⊕ B', analogy: '判异:不同为 1,相同为 0' }
]
const truthRows = [
{ a: 0, b: 0 },
{ a: 0, b: 1 },
{ a: 1, b: 0 },
{ a: 1, b: 1 }
{ a: 0, b: 0, and: 0, or: 0, not: 1, xor: 0 },
{ a: 0, b: 1, and: 0, or: 1, not: 1, xor: 1 },
{ a: 1, b: 0, and: 0, or: 1, not: 0, xor: 1 },
{ a: 1, b: 1, and: 1, or: 1, not: 0, xor: 0 }
]
const gateOutput = (name, a, b) => {
switch (name) {
case 'AND':
return a && b ? 1 : 0
case 'OR':
return a || b ? 1 : 0
case 'NOT':
return a ? 0 : 1
case 'XOR':
return a !== b ? 1 : 0
default:
return 0
}
}
</script>
<style scoped>
@@ -127,11 +64,7 @@ const gateOutput = (name, a, b) => {
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
flex-wrap: wrap;
margin-bottom: 0.5rem;
}
.demo-header .title {
@@ -139,169 +72,29 @@ const gateOutput = (name, a, b) => {
font-size: 1rem;
}
.demo-header .subtitle {
.intro {
font-size: 0.9rem;
color: var(--vp-c-text-2);
font-size: 0.82rem;
margin-left: 0.5rem;
}
.control-panel {
display: flex;
align-items: center;
gap: 0.6rem;
margin-bottom: 0.75rem;
flex-wrap: wrap;
padding: 0.5rem 0.65rem;
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
}
.panel-hint {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.current-state {
font-size: 0.8rem;
color: var(--vp-c-text-2);
margin-left: auto;
font-variant-numeric: tabular-nums;
}
.input-item {
display: inline-flex;
align-items: center;
gap: 0.4rem;
background: var(--vp-c-bg-alt);
border: 1px solid var(--vp-c-divider);
border-radius: 999px;
padding: 0.2rem 0.5rem;
font-size: 0.85rem;
}
.input-label {
font-size: 0.82rem;
color: var(--vp-c-text-2);
}
.input-btn {
width: 28px;
height: 28px;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg-alt);
border-radius: 50%;
cursor: pointer;
font-weight: bold;
transition: all 0.2s;
}
.input-btn.on {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.gate-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.gate-card {
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
padding: 0.55rem;
display: flex;
flex-direction: column;
gap: 0.35rem;
}
.gate-top {
display: flex;
align-items: center;
justify-content: space-between;
}
.gate-name {
font-weight: bold;
font-size: 0.85rem;
color: var(--vp-c-brand-1);
}
.gate-formula {
font-family: monospace;
font-size: 0.72rem;
color: var(--vp-c-text-3);
}
.gate-analogy {
font-size: 0.72rem;
color: var(--vp-c-text-2);
line-height: 1.3;
}
.gate-output-row {
display: flex;
align-items: center;
gap: 0.35rem;
margin-top: 0.1rem;
}
.output-label {
font-size: 0.7rem;
color: var(--vp-c-text-3);
}
.output-hint {
font-size: 0.68rem;
color: var(--vp-c-text-3);
}
.output-value {
width: 24px;
height: 24px;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
background: var(--vp-c-bg-alt);
font-weight: bold;
font-size: 0.85rem;
flex-shrink: 0;
}
.output-value.on {
background: var(--vp-c-success);
color: white;
border-color: var(--vp-c-success);
margin: 0 0 0.75rem;
line-height: 1.5;
}
.truth-section {
margin-bottom: 0;
}
.table-title {
font-weight: bold;
font-size: 0.82rem;
margin-bottom: 0.4rem;
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
font-size: 0.8rem;
font-size: 0.88rem;
margin-bottom: 0.75rem;
}
th,
td {
border: 1px solid var(--vp-c-divider);
padding: 0;
height: 2rem;
padding: 0.4rem 0.5rem;
vertical-align: middle;
text-align: center;
font-variant-numeric: tabular-nums;
@@ -312,29 +105,36 @@ th {
font-weight: 600;
}
tr.highlight {
background: var(--vp-c-brand-soft);
.col-meaning {
margin: 0;
padding-left: 1.25rem;
font-size: 0.85rem;
color: var(--vp-c-text-2);
line-height: 1.6;
}
.col-meaning li {
margin-bottom: 0.25rem;
}
.col-meaning strong {
color: var(--vp-c-text-1);
font-variant-numeric: tabular-nums;
}
.info-box {
display: flex;
gap: 0.25rem;
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box strong {
white-space: nowrap;
flex-shrink: 0;
}
@media (max-width: 640px) {
.gate-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
</style>
@@ -1,13 +1,26 @@
<template>
<div class="register-demo">
<div class="demo-header">
<span class="title">寄存器存储状态的功能单元</span>
<span class="subtitle">改变输入不会改变存储值必须主动"写入"</span>
<span class="title">寄存器记住一个 0 1 的小单元</span>
<span class="subtitle">只有点写入时才会把当前输入记下来平时改输入不会影响已存的值</span>
</div>
<div class="why-what-box">
<p class="why-p">
<strong>为啥要看这个</strong>CPU 算到一半要暂时记住中间结果寄存器就是干这个的它和直接连线不同改输入不会立刻改变里面存的东西必须主动点一次写入才会更新
</p>
<p class="what-p">
<strong>这些词是啥</strong>
<span class="term">输入</span>你想写进去的 0 1
<span class="term">写入</span>点一下把当前输入锁进寄存器
<span class="term">存储值</span>寄存器里现在记着的数只有写入时才会变
<span class="term">输出</span>从寄存器读出来的数和存储值一样
</p>
</div>
<div class="control-panel">
<div class="control-left">
<span class="ctrl-label">输入</span>
<label class="ctrl-group">
<span class="ctrl-label">输入</span>
<button
class="input-toggle"
:class="{ on: inputData === 1 }"
@@ -15,87 +28,33 @@
>
{{ inputData }}
</button>
</div>
</label>
<button class="write-btn" :class="{ flash: isWriting }" @click="writeOnce">
写入寄存器
写入
</button>
<div class="control-right">
<span class="chip">存储值{{ storedData }}</span>
<span class="chip" :class="{ chip_on: storedData === 1 }">输出{{ storedData === 1 ? '1 ✓' : '0' }}</span>
</div>
<label class="ctrl-group">
<span class="ctrl-label">存储</span>
<span class="stored-val" :class="{ on: storedData === 1 }">{{ storedData }}</span>
</label>
<span class="ctrl-group">
<span class="ctrl-label">输出</span>
<span class="output-val" :class="{ on: storedData === 1 }">{{ storedData }}</span>
</span>
</div>
<div class="demo-content">
<div class="flow-diagram">
<div class="flow-node input-node">
<div class="node-label">输入Data</div>
<div class="node-value" :class="{ on: inputData === 1 }">{{ inputData }}</div>
<div class="node-hint">点左侧按钮切换</div>
</div>
<div class="flow-arrow" :class="{ active: isWriting }">
<div class="arrow-line" />
<div class="arrow-tag">{{ isWriting ? '写入中...' : '写入触发' }}</div>
<div class="arrow-head"></div>
</div>
<div class="flow-node register-node" :class="{ flashing: isWriting }">
<div class="node-label">D 触发器寄存器核心</div>
<div class="node-value" :class="{ on: storedData === 1 }">{{ storedData }}</div>
<div class="node-hint">{{ isWriting ? '正在锁存...' : '保持 (Hold)' }}</div>
</div>
<div class="flow-arrow" :class="{ active: storedData === 1 }">
<div class="arrow-line" />
<div class="arrow-tag">输出</div>
<div class="arrow-head"></div>
</div>
<div class="flow-node output-node" :class="{ on: storedData === 1 }">
<div class="node-label">输出Output</div>
<div class="bulb">{{ storedData === 1 ? '💡' : '🌑' }}</div>
<div class="node-hint">{{ storedData === 1 ? '亮(1' : '灭(0' }}</div>
</div>
</div>
<div class="state-table">
<div class="table-title">操作步骤说明</div>
<div class="state-rows">
<div class="state-row">
<span class="step-num"></span>
<span>"输入值"按钮切换输入0/1</span>
</div>
<div class="state-row">
<span class="step-num"></span>
<span>此时存储值<strong>不变</strong>这就是寄存器的意义</span>
</div>
<div class="state-row">
<span class="step-num"></span>
<span>"写入寄存器"输入值才被锁入</span>
</div>
<div class="state-row">
<span class="step-num"></span>
<span>写入后再改输入存储值依然<strong>保持</strong>不变</span>
</div>
</div>
<div class="diff-display">
<div class="diff-item">
<div class="diff-label">当前输入</div>
<div class="diff-value" :class="{ on: inputData === 1 }">{{ inputData }}</div>
</div>
<div class="diff-sep"></div>
<div class="diff-item">
<div class="diff-label">存储值</div>
<div class="diff-value" :class="{ on: storedData === 1 }">{{ storedData }}</div>
</div>
<div v-if="inputData === storedData" class="diff-same">当前相同</div>
</div>
<div class="visualization-area">
<div class="flow-strip">
<span class="flow-item">输入 {{ inputData }}</span>
<span class="flow-arrow" :class="{ active: isWriting }">{{ isWriting ? '写入中 →' : '— 点「写入」才更新 →' }}</span>
<span class="flow-item flow-store" :class="{ flash: isWriting }"> {{ storedData }}</span>
</div>
<p class="flow-hint">
{{ inputData !== storedData ? '输入和存储不一样:点「写入」会把当前输入记进去。' : '输入和存储已一致。' }}
</p>
</div>
<div class="info-box">
<strong>核心思想</strong>寄存器只在"写入"信号触发时更新其余时刻持续锁定当前这就是 CPU 在计算过程中稳定保存中间结果的原因
<strong>核心思想</strong>寄存器只在写入那一刻更新其余时间一直保持原来的所以 CPU 能稳定保存中间结果
</div>
</div>
</template>
@@ -126,41 +85,62 @@ const writeOnce = () => {
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.8rem;
flex-wrap: wrap;
margin-bottom: 0.5rem;
}
.demo-header .title {
display: block;
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
display: block;
font-size: 0.82rem;
margin-left: 0.5rem;
color: var(--vp-c-text-2);
font-weight: normal;
}
.why-what-box {
background: var(--vp-c-bg-alt);
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
padding: 0.65rem 0.85rem;
margin-bottom: 0.75rem;
font-size: 0.85rem;
color: var(--vp-c-text-2);
line-height: 1.55;
}
.why-what-box .why-p {
margin: 0 0 0.4rem;
}
.why-what-box .what-p {
margin: 0;
}
.why-what-box .term {
font-weight: 600;
color: var(--vp-c-text-1);
}
/* ---- control panel ---- */
.control-panel {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.7rem;
padding: 0.6rem 0.75rem;
gap: 0.6rem;
padding: 0.5rem 0.7rem;
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg);
margin-bottom: 0.8rem;
flex-wrap: wrap;
margin-bottom: 0.75rem;
}
.control-left {
display: flex;
.ctrl-group {
display: inline-flex;
align-items: center;
gap: 0.45rem;
gap: 0.35rem;
}
.ctrl-label {
@@ -169,9 +149,9 @@ const writeOnce = () => {
}
.input-toggle {
width: 2rem;
height: 2rem;
border-radius: 50%;
width: 2.2rem;
height: 2.2rem;
border-radius: 6px;
border: 2px solid var(--vp-c-divider);
background: var(--vp-c-bg-alt);
font-weight: bold;
@@ -187,260 +167,102 @@ const writeOnce = () => {
}
.write-btn {
padding: 0.3rem 0.75rem;
border-radius: 999px;
border: 2px solid var(--vp-c-warning);
padding: 0.35rem 0.8rem;
border-radius: 6px;
border: 2px solid var(--vp-c-warning-1, #d97706);
background: var(--vp-c-bg);
color: var(--vp-c-warning-1, #d97706);
font-size: 0.82rem;
font-size: 0.85rem;
font-weight: bold;
cursor: pointer;
transition: all 0.2s;
white-space: nowrap;
}
.write-btn:hover {
background: var(--vp-c-warning-soft);
background: var(--vp-c-warning-soft, rgba(217, 119, 6, 0.1));
}
.write-btn.flash {
background: var(--vp-c-warning);
background: var(--vp-c-warning-1, #d97706);
color: white;
transform: scale(0.96);
}
.control-right {
display: flex;
gap: 0.4rem;
flex-wrap: wrap;
margin-left: auto;
}
.chip {
font-size: 0.78rem;
padding: 0.2rem 0.45rem;
border-radius: 999px;
background: var(--vp-c-bg-alt);
border: 1px solid var(--vp-c-divider);
}
.chip_on {
border-color: var(--vp-c-brand);
color: var(--vp-c-brand);
}
/* ---- main content ---- */
.demo-content {
display: grid;
grid-template-columns: 1.5fr 1fr;
gap: 0.8rem;
}
/* ---- flow diagram ---- */
.flow-diagram {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg);
padding: 0.8rem;
display: flex;
.stored-val,
.output-val {
display: inline-flex;
align-items: center;
gap: 0.3rem;
flex-wrap: nowrap;
overflow-x: auto;
}
.flow-node {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.3rem;
flex-shrink: 0;
}
.node-label {
font-size: 0.72rem;
color: var(--vp-c-text-2);
text-align: center;
}
.node-value {
width: 2.4rem;
height: 2.4rem;
border-radius: 8px;
justify-content: center;
min-width: 2rem;
height: 2rem;
padding: 0 0.4rem;
border-radius: 6px;
border: 2px solid var(--vp-c-divider);
background: var(--vp-c-bg-alt);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
font-weight: bold;
font-family: monospace;
transition: all 0.3s;
font-size: 1rem;
}
.node-value.on {
.stored-val.on,
.output-val.on {
border-color: var(--vp-c-brand);
color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
}
.node-hint {
font-size: 0.7rem;
color: var(--vp-c-text-3);
.visualization-area {
margin-bottom: 0.75rem;
}
.register-node .node-value {
width: 3rem;
height: 3rem;
font-size: 1.5rem;
border: 3px solid var(--vp-c-text-1);
}
.register-node.flashing .node-value {
border-color: var(--vp-c-warning);
box-shadow: 0 0 10px var(--vp-c-warning-soft);
}
.bulb {
font-size: 1.8rem;
filter: grayscale(100%);
opacity: 0.4;
transition: all 0.3s;
}
.output-node.on .bulb {
filter: grayscale(0%);
opacity: 1;
text-shadow: 0 0 12px #facc15;
}
/* ---- arrows ---- */
.flow-arrow {
.flow-strip {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: center;
gap: 0.2rem;
flex-shrink: 0;
}
.arrow-line {
width: 28px;
height: 2px;
background: var(--vp-c-divider);
transition: background 0.3s;
}
.flow-arrow.active .arrow-line {
background: var(--vp-c-brand);
}
.arrow-tag {
font-size: 0.65rem;
color: var(--vp-c-text-3);
white-space: nowrap;
}
.arrow-head {
font-size: 0.8rem;
color: var(--vp-c-text-3);
}
/* ---- state table ---- */
.state-table {
gap: 0.4rem;
padding: 0.6rem 0.8rem;
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg);
padding: 0.8rem;
font-size: 0.9rem;
}
.table-title {
.flow-item {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.6rem;
}
.state-rows {
display: flex;
flex-direction: column;
gap: 0.4rem;
}
.state-row {
display: flex;
align-items: flex-start;
gap: 0.4rem;
font-size: 0.78rem;
color: var(--vp-c-text-2);
}
.step-num {
flex-shrink: 0;
font-weight: bold;
.flow-store {
color: var(--vp-c-brand);
}
.diff-display {
display: flex;
align-items: center;
gap: 0.5rem;
margin-top: 0.75rem;
padding: 0.5rem;
background: var(--vp-c-bg-alt);
border-radius: 6px;
}
.diff-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.2rem;
}
.diff-label {
font-size: 0.7rem;
color: var(--vp-c-text-2);
}
.diff-value {
width: 1.6rem;
height: 1.6rem;
.flow-store.flash {
box-shadow: 0 0 0 2px var(--vp-c-warning-1);
border-radius: 4px;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-family: monospace;
}
.diff-value.on {
border-color: var(--vp-c-brand);
color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
}
.diff-sep {
font-size: 1.1rem;
.flow-arrow {
color: var(--vp-c-text-3);
font-size: 0.82rem;
}
.flow-arrow.active {
color: var(--vp-c-warning-1);
font-weight: bold;
}
.diff-same {
font-size: 0.72rem;
color: var(--vp-c-text-3);
.flow-hint {
margin: 0.4rem 0 0;
font-size: 0.82rem;
color: var(--vp-c-text-2);
}
/* ---- info box ---- */
.info-box {
display: flex;
gap: 0.25rem;
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.8rem;
display: flex;
gap: 0.25rem;
}
.info-box strong {
@@ -448,9 +270,10 @@ const writeOnce = () => {
flex-shrink: 0;
}
@media (max-width: 760px) {
.demo-content {
grid-template-columns: 1fr;
@media (max-width: 520px) {
.control-panel {
flex-direction: column;
align-items: flex-start;
}
}
</style>
@@ -5,97 +5,43 @@
<span class="subtitle">Gate 电压决定电流能否通过</span>
</div>
<div class="control-panel">
<div class="control-left">
<span class="control-label">栅极输入Gate</span>
<button class="gate-toggle" :class="{ on: isOn }" @click="toggleSwitch">
{{ isOn ? '1高电压' : '0低电压' }}
</button>
</div>
<div class="control-right">
<span class="chip">通道{{ isOn ? '导通' : '断开' }}</span>
<span class="chip">输出{{ isOn ? '1' : '0' }}</span>
</div>
</div>
<div class="demo-content">
<div class="transistor-diagram">
<div class="gate-column">
<div class="gate-title">控制端 Gate</div>
<div class="gate-value" :class="{ on: isOn }">
{{ isOn ? '1' : '0' }}
<div class="states">
<div class="state-card">
<div class="state-label">Gate = 0低电压</div>
<div class="channel-row">
<span class="terminal">源极</span>
<div class="channel-track off">
<span class="block-icon"> 断开</span>
</div>
<div class="gate-arrow"> 控制</div>
<span class="terminal">漏极</span>
</div>
<div class="output-line">输出<strong>0</strong></div>
</div>
<div class="main-channel">
<div class="terminal-box">源极 Source</div>
<div class="channel-track" :class="{ on: isOn }">
<span v-if="!isOn" class="block-icon"></span>
<template v-else>
<span class="flow-dot d1" />
<span class="flow-dot d2" />
<span class="flow-dot d3" />
</template>
<div class="state-card">
<div class="state-label">Gate = 1高电压</div>
<div class="channel-row">
<span class="terminal">源极</span>
<div class="channel-track on">
<span class="flow-dot d1" />
<span class="flow-dot d2" />
<span class="flow-dot d3" />
<span class="flow-label">导通</span>
</div>
<div class="terminal-box">漏极 Drain</div>
</div>
<div class="result-line" :class="{ on: isOn }">
{{ isOn ? '电流通过:Source → Drain' : '电流被阻断:无法通过通道' }}
<span class="terminal">漏极</span>
</div>
<div class="output-line">输出<strong>1</strong></div>
</div>
<div class="truth-table">
<div class="table-title">晶体管状态表</div>
<table>
<thead>
<tr>
<th>Gate 输入</th>
<th>通道状态</th>
<th>输出</th>
</tr>
</thead>
<tbody>
<tr :class="{ highlight: !isOn }">
<td>0低电压</td>
<td>断开</td>
<td>0</td>
</tr>
<tr :class="{ highlight: isOn }">
<td>1高电压</td>
<td>导通</td>
<td>1</td>
</tr>
</tbody>
</table>
<div class="table-hint">
点上方按钮切换 Gate观察通道状态电流流动如何同步变化
</div>
</div>
</div>
<div class="step-guide">
<div class="step-item"> 改变 Gate 电压0/1</div>
<div class="step-item"> 通道变为断开/导通</div>
<div class="step-item"> 输出随之变成 0/1</div>
</div>
<div class="info-box">
<strong>核心思想</strong>晶体管本质电控开关Gate=1 导通Gate=0
时断开所有数字计算都建立在这种 0/1 开关之上
<strong>核心思想</strong>晶体管是电控开关Gate=1 导通Gate=0 断开所有数字计算都建立在这种 0/1 开关之上
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const isOn = ref(false)
const toggleSwitch = () => {
isOn.value = !isOn.value
}
// 纯静态展示,无需交互
</script>
<style scoped>
@@ -111,7 +57,7 @@ const toggleSwitch = () => {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.8rem;
margin-bottom: 0.75rem;
}
.demo-header .title {
@@ -125,166 +71,72 @@ const toggleSwitch = () => {
margin-left: 0.5rem;
}
.control-panel {
display: flex;
align-items: center;
padding: 0.65rem 0.75rem;
.states {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.75rem;
margin-bottom: 0.75rem;
}
.state-card {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg);
margin-bottom: 0.8rem;
flex-wrap: wrap;
padding: 0.75rem;
}
.control-left {
.state-label {
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-bottom: 0.5rem;
}
.channel-row {
display: flex;
align-items: center;
gap: 0.55rem;
gap: 0.5rem;
}
.control-label {
.terminal {
font-size: 0.82rem;
color: var(--vp-c-text-2);
}
.gate-toggle {
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg-alt);
border-radius: 999px;
padding: 0.3rem 0.65rem;
font-weight: bold;
cursor: pointer;
transition: all 0.2s;
}
.gate-toggle.on {
background: var(--vp-c-success-soft);
color: var(--vp-c-success-1);
border-color: var(--vp-c-success);
color: var(--vp-c-success-1);
background: var(--vp-c-success-soft);
}
.control-right {
display: flex;
gap: 0.4rem;
flex-wrap: wrap;
margin-left: auto;
}
.chip {
font-size: 0.78rem;
padding: 0.2rem 0.45rem;
border-radius: 999px;
background: var(--vp-c-bg-alt);
border: 1px solid var(--vp-c-divider);
}
.chip.active {
border-color: var(--vp-c-success);
}
.legend-chip {
font-size: 0.72rem;
padding: 0.16rem 0.42rem;
border-radius: 999px;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
color: var(--vp-c-text-2);
}
.demo-content {
display: grid;
grid-template-columns: 1.2fr 1fr;
gap: 0.9rem;
}
.transistor-diagram {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg);
padding: 0.8rem;
}
.gate-column {
display: flex;
align-items: center;
gap: 0.45rem;
margin-bottom: 0.7rem;
}
.gate-title {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.gate-value {
width: 2rem;
height: 2rem;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
border: 2px solid var(--vp-c-divider);
font-weight: bold;
}
.gate-value.on {
border-color: var(--vp-c-success);
color: var(--vp-c-success-1);
background: var(--vp-c-success-soft);
}
.gate-arrow {
font-size: 0.78rem;
color: var(--vp-c-text-2);
}
.main-channel {
display: grid;
grid-template-columns: 1fr 1.6fr 1fr;
align-items: center;
gap: 0.55rem;
}
.terminal-box {
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
background: var(--vp-c-bg-alt);
padding: 0.45rem;
text-align: center;
font-size: 0.78rem;
flex-shrink: 0;
}
.channel-track {
height: 2.4rem;
flex: 1;
min-height: 2.5rem;
border: 2px solid var(--vp-c-divider);
border-radius: 999px;
background: #e5e7eb;
position: relative;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.channel-track.off {
background: var(--vp-c-bg-alt);
}
.channel-track.on {
background: var(--vp-c-success-soft);
border-color: var(--vp-c-success);
}
.block-icon {
font-size: 1.1rem;
font-size: 0.9rem;
font-weight: bold;
color: var(--vp-c-text-3);
}
.flow-dot {
width: 0.42rem;
height: 0.42rem;
width: 0.4rem;
height: 0.4rem;
border-radius: 50%;
background: var(--vp-c-success);
position: absolute;
left: -8%;
left: -10%;
animation: flow 1.5s linear infinite;
}
@@ -296,92 +148,40 @@ const toggleSwitch = () => {
animation-delay: 0.9s;
}
.flow-label {
margin-left: 0.4rem;
font-size: 0.85rem;
color: var(--vp-c-success-1);
font-weight: 600;
}
@keyframes flow {
from {
left: -8%;
left: -10%;
}
to {
left: 105%;
}
}
.result-line {
margin-top: 0.7rem;
font-size: 0.82rem;
color: var(--vp-c-text-2);
padding: 0.45rem 0.55rem;
background: var(--vp-c-bg-alt);
border-radius: 6px;
}
.result-line.on {
color: var(--vp-c-success-1);
}
.truth-table {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg);
padding: 0.8rem;
}
.table-title {
font-weight: bold;
margin-bottom: 0.55rem;
.output-line {
margin-top: 0.5rem;
font-size: 0.9rem;
color: var(--vp-c-text-1);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.84rem;
}
th,
td {
border: 1px solid var(--vp-c-divider);
padding: 0.45rem;
text-align: center;
}
th {
background: var(--vp-c-bg-alt);
}
tr.highlight {
background: var(--vp-c-brand-soft);
}
.table-hint {
margin-top: 0.55rem;
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.step-guide {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0.45rem;
margin-top: 0.8rem;
}
.step-item {
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 6px;
padding: 0.45rem 0.5rem;
font-size: 0.78rem;
.output-line strong {
color: var(--vp-c-brand-1);
}
.info-box {
display: flex;
gap: 0.25rem;
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box strong {
@@ -389,12 +189,8 @@ tr.highlight {
flex-shrink: 0;
}
@media (max-width: 860px) {
.demo-content {
grid-template-columns: 1fr;
}
.step-guide {
@media (max-width: 640px) {
.states {
grid-template-columns: 1fr;
}
}