feat(docs): add interactive demos and complete content for development tools
- Add Vue components for interactive demos (SSH auth, regex, env vars, ports) - Complete markdown content for SSH, regex, environment variables, and ports - Remove placeholder "待实现" sections and replace with detailed guides - Add visual explanations for key concepts like ports and localhost - Include practical examples and troubleshooting tips - Add component for showing evolution from transistors to CPU - Improve documentation structure and navigation - Add security best practices for API keys and environment variables
This commit is contained in:
@@ -1,85 +1,128 @@
|
||||
<template>
|
||||
<div class="adder-demo">
|
||||
<div class="demo-header">
|
||||
<span class="title">加法器:用逻辑门做加法</span>
|
||||
<span class="subtitle">从逻辑门到算术运算</span>
|
||||
<span class="title">加法器:用逻辑门做二进制加法</span>
|
||||
<span class="subtitle">点击蓝色位按钮切换 0/1,观察进位如何逐位传递</span>
|
||||
</div>
|
||||
|
||||
<div class="demo-content">
|
||||
<div class="adder-controls">
|
||||
<div class="input-group">
|
||||
<label>A:</label>
|
||||
<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>
|
||||
<!-- 名词解释 -->
|
||||
<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>
|
||||
<div class="operator">
|
||||
+
|
||||
<span class="decimal">= {{ decimalA }}</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>
|
||||
<div class="input-group">
|
||||
<label>B:</label>
|
||||
<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>
|
||||
<span class="decimal">= {{ decimalB }}</span>
|
||||
</div>
|
||||
<div class="op-sign">=</div>
|
||||
<div class="result-inline">
|
||||
<span class="result-bin">{{ resultBinary }}</span>
|
||||
<span class="result-dec">(十进制 {{ resultDecimal }})</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 每位加法器展示 -->
|
||||
<div class="stages-label">逐位计算过程(从最低位开始)</div>
|
||||
<div class="adder-stages">
|
||||
<div
|
||||
v-for="(stage, idx) in stageData"
|
||||
:key="idx"
|
||||
class="stage"
|
||||
>
|
||||
<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>
|
||||
<span class="io-val">{{ stage.a }}</span>
|
||||
</div>
|
||||
<div class="io-row">
|
||||
<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">
|
||||
<span class="io-badge cin-badge">Cin</span>
|
||||
<span class="io-val">{{ stage.carryIn }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="decimal">= {{ decimalB }}</span>
|
||||
|
||||
<!-- 全加器框 -->
|
||||
<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>
|
||||
|
||||
<!-- 输出列 -->
|
||||
<div class="io-col outputs-col">
|
||||
<div class="io-row">
|
||||
<span class="io-badge s-badge">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-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>
|
||||
<div v-else-if="idx < stageData.length - 1" class="carry-hint no-carry">
|
||||
无进位
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="adder-visual">
|
||||
<div
|
||||
v-for="(s, i) in stages"
|
||||
:key="i"
|
||||
class="adder-stage"
|
||||
>
|
||||
<div class="stage-label">
|
||||
{{ s.label }}
|
||||
</div>
|
||||
<div class="stage-bits">
|
||||
<span class="bit-label">A{{ 3-i }}: {{ bitsA[i] }}</span>
|
||||
<span class="bit-label">B{{ 3-i }}: {{ bitsB[i] }}</span>
|
||||
<span
|
||||
v-if="i > 0"
|
||||
class="bit-label"
|
||||
>C{{ i }}: {{ carries[i-1] }}</span>
|
||||
</div>
|
||||
<div class="stage-result">
|
||||
<span class="sum-bit">S{{ 3-i }}: {{ sumBits[i] }}</span>
|
||||
<span class="carry-bit">C{{ i+1 }}: {{ carries[i] }}</span>
|
||||
</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-display">
|
||||
<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-decimal">{{ decimalA }} + {{ decimalB }} = {{ resultDecimal }}</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>加法器用全加器级联实现。每个全加器处理一位,产生"和"与"进位"。进位传递给下一位,就像我们手算加法一样。
|
||||
<strong>核心思想:</strong>每位全加器接收 A、B 和上一位的进位(Cin),输出本位的和(S)与向上传递的进位(Cout)——和我们手算竖式加法"逢二进一"完全一致。
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -98,47 +141,46 @@ const toggleBit = (arr, i) => {
|
||||
}
|
||||
}
|
||||
|
||||
const decimalA = computed(() => {
|
||||
return bitsA.value.reduce((acc, bit, i) => acc + bit * Math.pow(2, 3-i), 0)
|
||||
})
|
||||
const decimalA = computed(() =>
|
||||
bitsA.value.reduce((acc, bit, i) => acc + bit * Math.pow(2, 3 - i), 0)
|
||||
)
|
||||
|
||||
const decimalB = computed(() => {
|
||||
return bitsB.value.reduce((acc, bit, i) => acc + bit * Math.pow(2, 3-i), 0)
|
||||
})
|
||||
const decimalB = computed(() =>
|
||||
bitsB.value.reduce((acc, bit, i) => acc + bit * Math.pow(2, 3 - i), 0)
|
||||
)
|
||||
|
||||
const carries = computed(() => {
|
||||
const c = [0, 0, 0, 0]
|
||||
const stageData = computed(() => {
|
||||
const stages = []
|
||||
let carry = 0
|
||||
const posNames = ['最低位', '次低位', '次高位', '最高位']
|
||||
for (let i = 3; i >= 0; i--) {
|
||||
const sum = bitsA.value[i] + bitsB.value[i] + (i < 3 ? c[i+1] : 0)
|
||||
c[i] = sum >= 2 ? 1 : 0
|
||||
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],
|
||||
a,
|
||||
b,
|
||||
carryIn: stages.length > 0 ? carry : null,
|
||||
sum,
|
||||
carryOut
|
||||
})
|
||||
carry = carryOut
|
||||
}
|
||||
return c
|
||||
return stages
|
||||
})
|
||||
|
||||
const sumBits = computed(() => {
|
||||
const s = [0, 0, 0, 0]
|
||||
for (let i = 3; i >= 0; i--) {
|
||||
const sum = bitsA.value[i] + bitsB.value[i] + (i < 3 ? carries.value[i+1] : 0)
|
||||
s[i] = sum % 2
|
||||
}
|
||||
return s
|
||||
})
|
||||
const sumBits = computed(() => stageData.value.map((s) => s.sum).reverse())
|
||||
|
||||
const resultBinary = computed(() => {
|
||||
const allBits = [carries.value[0], ...sumBits.value]
|
||||
return allBits.join('')
|
||||
const lastCarry = stageData.value[stageData.value.length - 1]?.carryOut || 0
|
||||
return (lastCarry ? lastCarry.toString() : '') + sumBits.value.join('')
|
||||
})
|
||||
|
||||
const resultDecimal = computed(() => {
|
||||
return decimalA.value + decimalB.value
|
||||
})
|
||||
|
||||
const stages = [
|
||||
{ label: '第4位 (个位)' },
|
||||
{ label: '第3位' },
|
||||
{ label: '第2位' },
|
||||
{ label: '第1位 (最高位)' }
|
||||
]
|
||||
const resultDecimal = computed(() => decimalA.value + decimalB.value)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -154,44 +196,93 @@ const stages = [
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
margin-bottom: 0.65rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.demo-header .title { font-weight: bold; font-size: 1rem; }
|
||||
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
|
||||
.demo-header .title {
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.adder-controls {
|
||||
.demo-header .subtitle {
|
||||
color: var(--vp-c-text-2);
|
||||
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;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
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.5rem;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.input-group label {
|
||||
.group-label {
|
||||
font-size: 0.8rem;
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bits {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
.bit-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
background: var(--vp-c-bg);
|
||||
background: var(--vp-c-bg-alt);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.85rem;
|
||||
font-weight: bold;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
@@ -202,87 +293,168 @@ const stages = [
|
||||
}
|
||||
|
||||
.decimal {
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.82rem;
|
||||
color: var(--vp-c-text-2);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.operator {
|
||||
font-size: 1.2rem;
|
||||
.op-sign {
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-brand);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.result-inline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
.result-bin {
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.adder-visual {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
overflow-x: auto;
|
||||
.result-dec {
|
||||
font-size: 0.8rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.adder-stage {
|
||||
flex: 1;
|
||||
min-width: 100px;
|
||||
padding: 0.5rem;
|
||||
/* 阶段 */
|
||||
.stages-label {
|
||||
font-size: 0.82rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.4rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.adder-stages {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 0.45rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.stage {
|
||||
background: var(--vp-c-bg);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 6px;
|
||||
border-radius: 8px;
|
||||
padding: 0.55rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.stage-label {
|
||||
font-size: 0.75rem;
|
||||
.stage-title {
|
||||
font-size: 0.72rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-text-2);
|
||||
text-align: center;
|
||||
margin-bottom: 0.5rem;
|
||||
padding-bottom: 0.3rem;
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.stage-bits {
|
||||
.stage-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
.io-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
margin-bottom: 0.5rem;
|
||||
gap: 0.22rem;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bit-label {
|
||||
color: var(--vp-c-text-2);
|
||||
.io-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
.stage-result {
|
||||
.io-badge {
|
||||
font-size: 0.62rem;
|
||||
font-weight: bold;
|
||||
padding: 0.05rem 0.3rem;
|
||||
border-radius: 3px;
|
||||
flex-shrink: 0;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.a-badge { background: var(--vp-c-brand); }
|
||||
.b-badge { background: #8b5cf6; }
|
||||
.cin-badge { background: #d97706; }
|
||||
.s-badge { background: var(--vp-c-success, #16a34a); }
|
||||
.cout-badge { background: #d97706; }
|
||||
|
||||
.io-val {
|
||||
font-weight: bold;
|
||||
font-family: monospace;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.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;
|
||||
gap: 0.25rem;
|
||||
font-size: 0.8rem;
|
||||
align-items: center;
|
||||
gap: 0.1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.fa-label {
|
||||
font-size: 0.68rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sum-bit {
|
||||
color: var(--vp-c-brand);
|
||||
.fa-hint {
|
||||
font-size: 0.6rem;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
.carry-bit {
|
||||
color: var(--vp-c-warning);
|
||||
/* 进位提示 */
|
||||
.carry-hint {
|
||||
font-size: 0.65rem;
|
||||
color: #d97706;
|
||||
text-align: center;
|
||||
padding: 0.15rem 0;
|
||||
}
|
||||
|
||||
.result-display {
|
||||
.carry-hint.no-carry {
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
/* 结果栏 */
|
||||
.result-bar {
|
||||
background: var(--vp-c-bg-alt);
|
||||
padding: 0.75rem;
|
||||
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.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.result-row:last-child {
|
||||
margin-bottom: 0;
|
||||
gap: 0.4rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.result-label {
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.82rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
@@ -292,20 +464,36 @@ const stages = [
|
||||
color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.result-decimal {
|
||||
.result-eq {
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-success);
|
||||
color: var(--vp-c-success, #16a34a);
|
||||
}
|
||||
|
||||
/* info box */
|
||||
.info-box {
|
||||
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: 700px) {
|
||||
.adder-stages {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 440px) {
|
||||
.adder-stages {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+376
-430
File diff suppressed because it is too large
Load Diff
+151
-164
@@ -2,105 +2,85 @@
|
||||
<div class="cpu-arch-demo">
|
||||
<div class="demo-header">
|
||||
<span class="title">CPU 架构全貌</span>
|
||||
<span class="subtitle">从门电路到处理器</span>
|
||||
<span class="subtitle">从功能单元到完整核心</span>
|
||||
</div>
|
||||
|
||||
<div class="demo-content">
|
||||
<div class="architecture-layers">
|
||||
<div
|
||||
v-for="(layer, i) in layers"
|
||||
:key="layer.name"
|
||||
class="layer"
|
||||
:class="{ active: activeLayer === i }"
|
||||
@click="activeLayer = activeLayer === i ? null : i"
|
||||
>
|
||||
<div class="layer-header">
|
||||
<span class="layer-icon">{{ layer.icon }}</span>
|
||||
<span class="layer-name">{{ layer.name }}</span>
|
||||
<span class="layer-count">{{ layer.count }}</span>
|
||||
</div>
|
||||
<Transition name="fade">
|
||||
<div
|
||||
v-if="activeLayer === i"
|
||||
class="layer-detail"
|
||||
>
|
||||
<p class="detail-desc">
|
||||
{{ layer.desc }}
|
||||
</p>
|
||||
<div class="detail-example">
|
||||
<span class="example-label">🌰 例子:</span>
|
||||
<span class="example-content">{{ layer.example }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cpu-components">
|
||||
<div class="comp-title">
|
||||
CPU 核心组件
|
||||
</div>
|
||||
<div class="comp-grid">
|
||||
<div
|
||||
v-for="comp in components"
|
||||
:key="comp.name"
|
||||
class="comp-item"
|
||||
>
|
||||
<div class="architecture-overview">
|
||||
<div class="overview-title">核心组件一览(静态展示)</div>
|
||||
<div class="overview-grid">
|
||||
<div v-for="comp in components" :key="comp.name" class="overview-card">
|
||||
<div class="card-top">
|
||||
<span class="comp-icon">{{ comp.icon }}</span>
|
||||
<span class="comp-name">{{ comp.name }}</span>
|
||||
<span class="comp-desc">{{ comp.desc }}</span>
|
||||
</div>
|
||||
<div class="comp-desc">{{ comp.desc }}</div>
|
||||
<div class="comp-role">{{ comp.role }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="instruction-flow">
|
||||
<div class="flow-title">一条指令在 CPU 内部的流动</div>
|
||||
<div class="flow-steps">
|
||||
<div
|
||||
v-for="(step, index) in instructionFlow"
|
||||
:key="step.name"
|
||||
class="flow-step"
|
||||
>
|
||||
<span class="step-index">{{ index + 1 }}</span>
|
||||
<span class="step-name">{{ step.name }}</span>
|
||||
<span class="step-desc">{{ step.desc }}</span>
|
||||
<span
|
||||
v-if="index < instructionFlow.length - 1"
|
||||
class="step-arrow"
|
||||
aria-hidden="true"
|
||||
>
|
||||
→
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<strong>核心思想:</strong>CPU是层次化构建的:晶体管→逻辑门→功能单元→处理器。每一层都是下一层的"积木",最终形成能执行程序的"大脑"。
|
||||
<strong>核心思想:</strong
|
||||
>CPU 不是单一部件,而是多个功能单元的有序协作:控制器负责调度,ALU 负责计算,寄存器负责高速暂存,总线负责连接与传输。
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const activeLayer = ref(null)
|
||||
|
||||
const layers = [
|
||||
const components = [
|
||||
{
|
||||
name: '晶体管',
|
||||
icon: '⚡',
|
||||
count: '数十亿个',
|
||||
desc: '最基本的开关单元,用半导体材料制成。现代CPU包含数十亿个晶体管。',
|
||||
example: 'Apple M2 芯片有约 200 亿个晶体管'
|
||||
icon: '🎮',
|
||||
name: '控制器(CU)',
|
||||
desc: '负责取指、解码和发出控制信号',
|
||||
role: '像指挥员,安排每个模块何时工作'
|
||||
},
|
||||
{
|
||||
name: '逻辑门',
|
||||
icon: '🔌',
|
||||
count: '数亿个',
|
||||
desc: '由多个晶体管组成,实现基本逻辑运算(AND、OR、NOT等)。',
|
||||
example: '一个 AND 门需要 2-6 个晶体管'
|
||||
icon: '📊',
|
||||
name: 'ALU',
|
||||
desc: '执行加减与、或、比较等运算',
|
||||
role: '像计算器,完成核心算术与逻辑处理'
|
||||
},
|
||||
{
|
||||
name: '功能单元',
|
||||
icon: '🔧',
|
||||
count: '数百个',
|
||||
desc: '由逻辑门组成,实现特定功能:加法器、多路选择器、寄存器等。',
|
||||
example: '一个 64 位加法器需要约 1000 个逻辑门'
|
||||
icon: '📁',
|
||||
name: '寄存器组',
|
||||
desc: '保存当前最常用的数据和中间结果',
|
||||
role: '像桌面便签,读写速度远高于内存'
|
||||
},
|
||||
{
|
||||
name: 'CPU 核心',
|
||||
icon: '🧠',
|
||||
count: '1-128个',
|
||||
desc: '包含完整的运算和控制能力,能独立执行指令流。',
|
||||
example: 'Intel i9-13900K 有 24 核心'
|
||||
icon: '🚌',
|
||||
name: '内部总线',
|
||||
desc: '在模块间传输数据、地址和控制信息',
|
||||
role: '像高速通道,把各组件连接成整体'
|
||||
}
|
||||
]
|
||||
|
||||
const components = [
|
||||
{ icon: '📊', name: 'ALU', desc: '算术逻辑单元,做加减乘除和逻辑运算' },
|
||||
{ icon: '📁', name: '寄存器', desc: '超高速存储,存放正在处理的数据' },
|
||||
{ icon: '🎮', name: '控制器', desc: '指挥官,解码指令并协调各部件' },
|
||||
{ icon: '🚌', name: '总线', desc: '数据高速公路,连接各部件' }
|
||||
const instructionFlow = [
|
||||
{ name: '取指', desc: '控制器从缓存/内存取来指令' },
|
||||
{ name: '解码', desc: '识别指令类型与需要的操作数' },
|
||||
{ name: '执行', desc: 'ALU 或其他单元完成具体运算' },
|
||||
{ name: '写回', desc: '结果写入寄存器,供后续指令使用' }
|
||||
]
|
||||
</script>
|
||||
|
||||
@@ -109,115 +89,59 @@ const components = [
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
padding: 1.25rem;
|
||||
margin: 1.25rem 0;
|
||||
}
|
||||
|
||||
.demo-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.demo-header .title { font-weight: bold; font-size: 1rem; }
|
||||
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
|
||||
|
||||
.architecture-layers {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.layer {
|
||||
background: var(--vp-c-bg);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 6px;
|
||||
padding: 0.5rem 0.75rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.layer:hover {
|
||||
border-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.layer.active {
|
||||
border-color: var(--vp-c-brand);
|
||||
background: var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
.layer-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.layer-icon {
|
||||
.demo-header .title {
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.layer-name {
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.layer-count {
|
||||
margin-left: auto;
|
||||
font-size: 0.8rem;
|
||||
.demo-header .subtitle {
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.layer-detail {
|
||||
margin-top: 0.5rem;
|
||||
padding-top: 0.5rem;
|
||||
border-top: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.detail-desc {
|
||||
font-size: 0.85rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.overview-title,
|
||||
.flow-title {
|
||||
font-weight: bold;
|
||||
font-size: 0.92rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.detail-example {
|
||||
font-size: 0.8rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.example-label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.cpu-components {
|
||||
background: var(--vp-c-bg-alt);
|
||||
padding: 0.75rem;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.comp-title {
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.comp-grid {
|
||||
.overview-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 0.5rem;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.comp-item {
|
||||
.overview-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0.5rem;
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 4px;
|
||||
gap: 0.35rem;
|
||||
padding: 0.7rem;
|
||||
background: var(--vp-c-bg-alt);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.card-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
}
|
||||
|
||||
.comp-icon {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.comp-name {
|
||||
@@ -226,27 +150,90 @@ const components = [
|
||||
}
|
||||
|
||||
.comp-desc {
|
||||
font-size: 0.78rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.comp-role {
|
||||
font-size: 0.78rem;
|
||||
color: var(--vp-c-text-1);
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 4px;
|
||||
padding: 0.25rem 0.4rem;
|
||||
}
|
||||
|
||||
.instruction-flow {
|
||||
margin-top: 1rem;
|
||||
background: var(--vp-c-bg);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.flow-steps {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flow-step {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 999px;
|
||||
padding: 0.35rem 0.55rem;
|
||||
}
|
||||
|
||||
.step-index {
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
border-radius: 50%;
|
||||
background: var(--vp-c-brand-soft);
|
||||
color: var(--vp-c-brand-1);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.72rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.step-name {
|
||||
font-size: 0.78rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.step-desc {
|
||||
font-size: 0.75rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.fade-enter-from, .fade-leave-to {
|
||||
opacity: 0;
|
||||
.step-arrow {
|
||||
margin-left: 0.1rem;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background: var(--vp-c-bg-alt);
|
||||
padding: 0.75rem;
|
||||
padding: 0.85rem;
|
||||
border-radius: 6px;
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-text-2);
|
||||
margin-top: 0.75rem;
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.info-box strong {
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 680px) {
|
||||
.overview-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<div class="evolution-flow-demo">
|
||||
<div class="demo-header">
|
||||
<span class="title">全景图:从沙子到智能</span>
|
||||
<span class="subtitle">每一层都是对下一层的抽象封装</span>
|
||||
</div>
|
||||
|
||||
<div class="flow-list">
|
||||
<div v-for="(step, index) in steps" :key="index" class="flow-row">
|
||||
<!-- 卡片 -->
|
||||
<div class="step-card">
|
||||
<div class="card-left">
|
||||
<span class="step-icon">{{ step.icon }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-title">{{ step.title }}</div>
|
||||
<div class="card-desc">{{ step.desc }}</div>
|
||||
</div>
|
||||
<div class="card-right">
|
||||
<span class="card-count">{{ step.count }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 箭头 -->
|
||||
<div v-if="index < steps.length - 1" class="flow-arrow">
|
||||
<div class="arrow-line" />
|
||||
<div class="arrow-action">{{ step.action }}</div>
|
||||
<div class="arrow-sym">↓</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<strong>核心思想:</strong>计算机的本质是"开关的组合"。通过一层层的抽象封装,最底层的物理材料最终变成了能执行任意逻辑的通用计算平台。
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const steps = [
|
||||
{
|
||||
icon: '🏖️',
|
||||
title: '沙子(硅)',
|
||||
desc: '地球上最丰富的元素之一,提炼出高纯度硅',
|
||||
count: '原材料',
|
||||
action: '↓ 提纯 → 切割成晶圆'
|
||||
},
|
||||
{
|
||||
icon: '💿',
|
||||
title: '硅晶圆',
|
||||
desc: '直径 30cm 的单晶硅片,表面极其光滑',
|
||||
count: '基底',
|
||||
action: '↓ 光刻 → 蚀刻 → 掺杂'
|
||||
},
|
||||
{
|
||||
icon: '⚡',
|
||||
title: '晶体管(开关)',
|
||||
desc: 'Gate=1 导通,Gate=0 断开,用电压控制电流',
|
||||
count: '数百亿个 / 芯片',
|
||||
action: '↓ 组合成逻辑电路'
|
||||
},
|
||||
{
|
||||
icon: '🔌',
|
||||
title: '逻辑门',
|
||||
desc: 'AND / OR / NOT / XOR,实现基本布尔运算',
|
||||
count: '数十亿个',
|
||||
action: '↓ 组合成功能模块'
|
||||
},
|
||||
{
|
||||
icon: '🔧',
|
||||
title: '功能单元',
|
||||
desc: '加法器、寄存器、多路选择器……各司其职',
|
||||
count: '数百个',
|
||||
action: '↓ 集成为完整处理器'
|
||||
},
|
||||
{
|
||||
icon: '🧠',
|
||||
title: 'CPU 核心',
|
||||
desc: 'ALU + 控制器 + 寄存器组,执行取指→解码→执行→写回',
|
||||
count: '1 ~ 128 核',
|
||||
action: '↓ 软件编程'
|
||||
},
|
||||
{
|
||||
icon: '💻',
|
||||
title: '软件应用',
|
||||
desc: '操作系统 / AI 模型 / 游戏 / 网页……一切皆指令',
|
||||
count: '无限可能',
|
||||
action: ''
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.evolution-flow-demo {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.demo-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.8rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.demo-header .title {
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.demo-header .subtitle {
|
||||
color: var(--vp-c-text-2);
|
||||
font-size: 0.82rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
/* 整体竖向流程 */
|
||||
.flow-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.flow-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
/* 卡片 */
|
||||
.step-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.65rem;
|
||||
background: var(--vp-c-bg);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 0.65rem 0.8rem;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
.step-card:hover {
|
||||
border-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.card-left {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
font-size: 0.78rem;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.card-right {
|
||||
flex-shrink: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.card-count {
|
||||
font-size: 0.72rem;
|
||||
color: var(--vp-c-text-3);
|
||||
background: var(--vp-c-bg-alt);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 999px;
|
||||
padding: 0.15rem 0.45rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 箭头区域 */
|
||||
.flow-arrow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.2rem 1rem;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
.arrow-line {
|
||||
width: 2px;
|
||||
height: 0.8rem;
|
||||
background: var(--vp-c-divider);
|
||||
margin-left: 1.3rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.arrow-action {
|
||||
font-size: 0.72rem;
|
||||
color: var(--vp-c-brand);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.arrow-sym {
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-brand);
|
||||
margin-left: auto;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
/* info box */
|
||||
.info-box {
|
||||
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 {
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
+830
-288
File diff suppressed because it is too large
Load Diff
+205
-365
@@ -2,308 +2,119 @@
|
||||
<div class="logic-gate-demo">
|
||||
<div class="demo-header">
|
||||
<span class="title">逻辑门:用开关做运算</span>
|
||||
<span class="subtitle">晶体管组合成基本运算单元</span>
|
||||
<span class="subtitle">切换输入 A / B,同屏观察四种门的输出</span>
|
||||
</div>
|
||||
|
||||
<div class="demo-content">
|
||||
<div class="gate-tabs">
|
||||
<button
|
||||
v-for="gate in gates"
|
||||
:key="gate.name"
|
||||
:class="['tab-btn', { active: activeGate === gate.name }]"
|
||||
@click="activeGate = gate.name"
|
||||
>
|
||||
{{ gate.name }}
|
||||
<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-display">
|
||||
<div class="gate-visual">
|
||||
<div class="inputs">
|
||||
<div class="input-item">
|
||||
<span>A:</span>
|
||||
<button
|
||||
class="input-btn"
|
||||
:class="{ on: inputA }"
|
||||
@click="inputA = !inputA"
|
||||
>
|
||||
{{ inputA ? '1' : '0' }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="input-item">
|
||||
<span>B:</span>
|
||||
<button
|
||||
class="input-btn"
|
||||
:class="{ on: inputB }"
|
||||
@click="inputB = !inputB"
|
||||
>
|
||||
{{ inputB ? '1' : '0' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gate-symbol">
|
||||
<svg
|
||||
viewBox="0 0 120 80"
|
||||
class="gate-svg"
|
||||
>
|
||||
<template v-if="activeGate === 'AND'">
|
||||
<path
|
||||
d="M20,20 L20,60 L60,60 Q90,60 90,40 Q90,20 60,20 Z"
|
||||
fill="none"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="90"
|
||||
y1="40"
|
||||
x2="110"
|
||||
y2="40"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="0"
|
||||
y1="30"
|
||||
x2="20"
|
||||
y2="30"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="0"
|
||||
y1="50"
|
||||
x2="20"
|
||||
y2="50"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="activeGate === 'OR'">
|
||||
<path
|
||||
d="M20,20 Q40,40 20,60 Q60,60 90,40 Q60,20 20,20"
|
||||
fill="none"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="90"
|
||||
y1="40"
|
||||
x2="110"
|
||||
y2="40"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="0"
|
||||
y1="30"
|
||||
x2="25"
|
||||
y2="30"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="0"
|
||||
y1="50"
|
||||
x2="25"
|
||||
y2="50"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="activeGate === 'NOT'">
|
||||
<polygon
|
||||
points="20,20 80,40 20,60"
|
||||
fill="none"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<circle
|
||||
cx="85"
|
||||
cy="40"
|
||||
r="5"
|
||||
fill="none"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="90"
|
||||
y1="40"
|
||||
x2="110"
|
||||
y2="40"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="0"
|
||||
y1="40"
|
||||
x2="20"
|
||||
y2="40"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="activeGate === 'XOR'">
|
||||
<path
|
||||
d="M25,20 Q45,40 25,60 Q65,60 95,40 Q65,20 25,20"
|
||||
fill="none"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<path
|
||||
d="M15,20 Q35,40 15,60"
|
||||
fill="none"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="95"
|
||||
y1="40"
|
||||
x2="115"
|
||||
y2="40"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="0"
|
||||
y1="30"
|
||||
x2="30"
|
||||
y2="30"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="0"
|
||||
y1="50"
|
||||
x2="30"
|
||||
y2="50"
|
||||
stroke="var(--vp-c-brand)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
</template>
|
||||
</svg>
|
||||
<div class="gate-name">
|
||||
{{ activeGate }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="output">
|
||||
<span class="output-label">输出:</span>
|
||||
<span
|
||||
class="output-value"
|
||||
:class="{ on: output }"
|
||||
>{{ output ? '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="truth-table-mini">
|
||||
<div class="table-title">
|
||||
{{ activeGate }} 真值表
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>A</th>
|
||||
<th>B</th>
|
||||
<th>输出</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="row in currentTruthTable"
|
||||
:key="row.a + '-' + row.b"
|
||||
:class="{ highlight: row.a === (inputA ? 1 : 0) && (activeGate === 'NOT' || row.b === (inputB ? 1 : 0)) }"
|
||||
>
|
||||
<td>{{ row.a }}</td>
|
||||
<td>{{ row.b }}</td>
|
||||
<td>{{ row.out }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<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>
|
||||
|
||||
<div class="gate-explanation">
|
||||
<div class="exp-title">
|
||||
{{ currentGate.expTitle }}
|
||||
</div>
|
||||
<div class="exp-content">
|
||||
{{ currentGate.expContent }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="truth-section">
|
||||
<div class="table-title">四种门真值表对照(高亮行 = 当前输入)</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>A</th>
|
||||
<th>B</th>
|
||||
<th>AND</th>
|
||||
<th>OR</th>
|
||||
<th>NOT(A)</th>
|
||||
<th>XOR</th>
|
||||
</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)
|
||||
}"
|
||||
>
|
||||
<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>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<strong>核心思想:</strong>逻辑门用晶体管的"开关"组合实现基本运算。AND门像"串联开关"(两个都开才通),OR门像"并联开关"(任一个开就通)。
|
||||
<strong>核心思想:</strong>逻辑门用晶体管的"开关"组合实现基本运算——AND 像串联、OR 像并联、NOT 取反、XOR 判异。所有复杂计算都由这四种基础操作构建而来。
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const activeGate = ref('AND')
|
||||
const inputA = ref(false)
|
||||
const inputB = ref(false)
|
||||
|
||||
const gates = [
|
||||
{
|
||||
name: 'AND',
|
||||
expTitle: 'AND门:两个都为1才输出1',
|
||||
expContent: '就像串联的两个开关,必须两个都按下灯才会亮。用于"同时满足多个条件"的场景。'
|
||||
},
|
||||
{
|
||||
name: 'OR',
|
||||
expTitle: 'OR门:任一个为1就输出1',
|
||||
expContent: '就像并联的两个开关,按任意一个灯就会亮。用于"满足任一条件"的场景。'
|
||||
},
|
||||
{
|
||||
name: 'NOT',
|
||||
expTitle: 'NOT门:取反,0变1,1变0',
|
||||
expContent: '就像一个反相器,输入开就输出关,输入关就输出开。用于"否定"的场景。'
|
||||
},
|
||||
{
|
||||
name: 'XOR',
|
||||
expTitle: 'XOR门:相同为0,不同为1',
|
||||
expContent: '就像"异或"判断,两个输入不同才输出1。用于比较两个值是否不同。'
|
||||
}
|
||||
{ name: 'AND', formula: 'A && B', analogy: '串联:都为 1 才输出 1' },
|
||||
{ name: 'OR', formula: 'A || B', analogy: '并联:任一为 1 就输出 1' },
|
||||
{ name: 'NOT', formula: '!A', analogy: '取反:0→1,1→0' },
|
||||
{ name: 'XOR', formula: 'A ⊕ B', analogy: '判异:不同为 1,相同为 0' }
|
||||
]
|
||||
|
||||
const currentGate = computed(() => gates.find(g => g.name === activeGate.value))
|
||||
const truthRows = [
|
||||
{ a: 0, b: 0 },
|
||||
{ a: 0, b: 1 },
|
||||
{ a: 1, b: 0 },
|
||||
{ a: 1, b: 1 }
|
||||
]
|
||||
|
||||
const output = computed(() => {
|
||||
const a = inputA.value
|
||||
const b = inputB.value
|
||||
switch (activeGate.value) {
|
||||
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
|
||||
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
|
||||
}
|
||||
})
|
||||
|
||||
const currentTruthTable = computed(() => {
|
||||
if (activeGate.value === 'NOT') {
|
||||
return [
|
||||
{ a: 0, b: '-', out: 1 },
|
||||
{ a: 1, b: '-', out: 0 }
|
||||
]
|
||||
}
|
||||
const table = []
|
||||
for (let a = 0; a <= 1; a++) {
|
||||
for (let b = 0; b <= 1; b++) {
|
||||
let out = 0
|
||||
switch (activeGate.value) {
|
||||
case 'AND': out = a && b ? 1 : 0; break
|
||||
case 'OR': out = a || b ? 1 : 0; break
|
||||
case 'XOR': out = a !== b ? 1 : 0; break
|
||||
}
|
||||
table.push({ a, b, out })
|
||||
}
|
||||
}
|
||||
return table
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -320,65 +131,66 @@ const currentTruthTable = computed(() => {
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.demo-header .title { font-weight: bold; font-size: 1rem; }
|
||||
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
|
||||
|
||||
.gate-tabs {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.tab-btn {
|
||||
padding: 0.4rem 0.8rem;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.85rem;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.tab-btn.active {
|
||||
background: var(--vp-c-brand);
|
||||
color: white;
|
||||
border-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.gate-display {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.gate-visual {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
.demo-header .title {
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.inputs {
|
||||
.demo-header .subtitle {
|
||||
color: var(--vp-c-text-2);
|
||||
font-size: 0.82rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.control-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
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: flex;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
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: 36px;
|
||||
height: 36px;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
background: var(--vp-c-bg);
|
||||
border-radius: 4px;
|
||||
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;
|
||||
@@ -390,44 +202,76 @@ const currentTruthTable = computed(() => {
|
||||
border-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.gate-symbol {
|
||||
width: 120px;
|
||||
text-align: center;
|
||||
.gate-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.gate-svg {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
.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.9rem;
|
||||
margin-top: 0.25rem;
|
||||
color: var(--vp-c-brand);
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.output {
|
||||
.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.5rem;
|
||||
gap: 0.35rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
.output-label {
|
||||
font-size: 0.85rem;
|
||||
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: 36px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
background: var(--vp-c-bg);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 4px;
|
||||
background: var(--vp-c-bg-alt);
|
||||
font-weight: bold;
|
||||
font-size: 1.1rem;
|
||||
font-size: 0.85rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.output-value.on {
|
||||
@@ -436,56 +280,42 @@ const currentTruthTable = computed(() => {
|
||||
border-color: var(--vp-c-success);
|
||||
}
|
||||
|
||||
.truth-table-mini {
|
||||
flex: 1;
|
||||
min-width: 150px;
|
||||
.truth-section {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.table-title {
|
||||
font-weight: bold;
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.82rem;
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
th, td {
|
||||
th,
|
||||
td {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
padding: 0.3rem 0.5rem;
|
||||
padding: 0;
|
||||
height: 2rem;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
th {
|
||||
background: var(--vp-c-bg-alt);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
tr.highlight {
|
||||
background: var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
.gate-explanation {
|
||||
width: 100%;
|
||||
margin-top: 1rem;
|
||||
padding: 0.75rem;
|
||||
background: var(--vp-c-bg-alt);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.exp-title {
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.exp-content {
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background: var(--vp-c-bg-alt);
|
||||
padding: 0.75rem;
|
||||
@@ -497,4 +327,14 @@ tr.highlight {
|
||||
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>
|
||||
|
||||
@@ -0,0 +1,456 @@
|
||||
<template>
|
||||
<div class="register-demo">
|
||||
<div class="demo-header">
|
||||
<span class="title">寄存器:存储状态的功能单元</span>
|
||||
<span class="subtitle">改变输入不会改变存储值——必须主动"写入"</span>
|
||||
</div>
|
||||
|
||||
<div class="control-panel">
|
||||
<div class="control-left">
|
||||
<span class="ctrl-label">输入值</span>
|
||||
<button
|
||||
class="input-toggle"
|
||||
:class="{ on: inputData === 1 }"
|
||||
@click="inputData = inputData === 1 ? 0 : 1"
|
||||
>
|
||||
{{ inputData }}
|
||||
</button>
|
||||
</div>
|
||||
<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>
|
||||
</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>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<strong>核心思想:</strong>寄存器只在"写入"信号触发时更新,其余时刻持续锁定当前值。这就是 CPU 能在计算过程中稳定保存中间结果的原因。
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const inputData = ref(0)
|
||||
const storedData = ref(0)
|
||||
const isWriting = ref(false)
|
||||
|
||||
const writeOnce = () => {
|
||||
isWriting.value = true
|
||||
storedData.value = inputData.value
|
||||
window.setTimeout(() => {
|
||||
isWriting.value = false
|
||||
}, 400)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.register-demo {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.demo-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.8rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.demo-header .title {
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.demo-header .subtitle {
|
||||
color: var(--vp-c-text-2);
|
||||
font-size: 0.82rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
/* ---- control panel ---- */
|
||||
.control-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.7rem;
|
||||
padding: 0.6rem 0.75rem;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
background: var(--vp-c-bg);
|
||||
margin-bottom: 0.8rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.control-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
}
|
||||
|
||||
.ctrl-label {
|
||||
font-size: 0.82rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.input-toggle {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
background: var(--vp-c-bg-alt);
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.input-toggle.on {
|
||||
border-color: var(--vp-c-brand);
|
||||
color: var(--vp-c-brand);
|
||||
background: var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
.write-btn {
|
||||
padding: 0.3rem 0.75rem;
|
||||
border-radius: 999px;
|
||||
border: 2px solid var(--vp-c-warning);
|
||||
background: var(--vp-c-bg);
|
||||
color: var(--vp-c-warning-1, #d97706);
|
||||
font-size: 0.82rem;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.write-btn:hover {
|
||||
background: var(--vp-c-warning-soft);
|
||||
}
|
||||
|
||||
.write-btn.flash {
|
||||
background: var(--vp-c-warning);
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
.node-value.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);
|
||||
}
|
||||
|
||||
.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 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
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 {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
background: var(--vp-c-bg);
|
||||
padding: 0.8rem;
|
||||
}
|
||||
|
||||
.table-title {
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
color: var(--vp-c-text-3);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.diff-same {
|
||||
font-size: 0.72rem;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
/* ---- info box ---- */
|
||||
.info-box {
|
||||
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 {
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.demo-content {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+283
-144
@@ -2,126 +2,88 @@
|
||||
<div class="transistor-demo">
|
||||
<div class="demo-header">
|
||||
<span class="title">晶体管:数字世界的开关</span>
|
||||
<span class="subtitle">一个开关如何变成计算能力</span>
|
||||
<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="switch-container">
|
||||
<div
|
||||
class="switch-area"
|
||||
@click="toggleSwitch"
|
||||
>
|
||||
<div class="transistor-symbol">
|
||||
<svg
|
||||
viewBox="0 0 100 80"
|
||||
class="transistor-svg"
|
||||
>
|
||||
<line
|
||||
x1="10"
|
||||
y1="40"
|
||||
x2="35"
|
||||
y2="40"
|
||||
stroke="var(--vp-c-text-1)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="65"
|
||||
y1="40"
|
||||
x2="90"
|
||||
y2="40"
|
||||
stroke="var(--vp-c-text-1)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="50"
|
||||
y1="20"
|
||||
x2="50"
|
||||
y2="35"
|
||||
stroke="var(--vp-c-text-1)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="50"
|
||||
y1="45"
|
||||
x2="50"
|
||||
y2="60"
|
||||
stroke="var(--vp-c-text-1)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<line
|
||||
x1="35"
|
||||
y1="30"
|
||||
x2="35"
|
||||
y2="50"
|
||||
stroke="var(--vp-c-text-1)"
|
||||
stroke-width="3"
|
||||
/>
|
||||
<line
|
||||
x1="65"
|
||||
y1="30"
|
||||
x2="65"
|
||||
y2="50"
|
||||
stroke="var(--vp-c-text-1)"
|
||||
stroke-width="3"
|
||||
/>
|
||||
<line
|
||||
x1="35"
|
||||
y1="40"
|
||||
x2="65"
|
||||
y2="40"
|
||||
stroke="var(--vp-c-text-1)"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<circle
|
||||
cx="50"
|
||||
cy="60"
|
||||
r="4"
|
||||
fill="var(--vp-c-text-1)"
|
||||
/>
|
||||
</svg>
|
||||
<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>
|
||||
<div class="switch-label">
|
||||
<span class="state-label">{{ isOn ? 'ON (1)' : 'OFF (0)' }}</span>
|
||||
<div
|
||||
class="current-flow"
|
||||
:class="{ active: isOn }"
|
||||
>
|
||||
<span class="flow-indicator">电流</span>
|
||||
</div>
|
||||
<div class="gate-arrow">↓ 控制</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>
|
||||
<div class="terminal-box">漏极 Drain</div>
|
||||
</div>
|
||||
|
||||
<div class="result-line" :class="{ on: isOn }">
|
||||
{{ isOn ? '电流通过:Source → Drain' : '电流被阻断:无法通过通道' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="truth-table">
|
||||
<div class="table-title">
|
||||
晶体管状态表
|
||||
</div>
|
||||
<div class="table-title">晶体管状态表</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>栅极(控制端)</th>
|
||||
<th>源极→漏极</th>
|
||||
<th>Gate 输入</th>
|
||||
<th>通道状态</th>
|
||||
<th>输出</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr :class="{ highlight: !isOn }">
|
||||
<td>低电压 (0)</td>
|
||||
<td>0(低电压)</td>
|
||||
<td>断开</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr :class="{ highlight: isOn }">
|
||||
<td>高电压 (1)</td>
|
||||
<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>晶体管就是一个用电控制的开关。给它高电压(1),它就导通;给低电压(0),它就断开。这是所有数字计算的基础。
|
||||
<strong>核心思想:</strong>晶体管本质是“电控开关”:Gate=1 时导通,Gate=0
|
||||
时断开。所有数字计算都建立在这种 0/1 开关之上。
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -149,94 +111,236 @@ const toggleSwitch = () => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.demo-header .title { font-weight: bold; font-size: 1rem; }
|
||||
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
|
||||
.demo-header .title {
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.demo-content {
|
||||
.demo-header .subtitle {
|
||||
color: var(--vp-c-text-2);
|
||||
font-size: 0.85rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.control-panel {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
align-items: center;
|
||||
padding: 0.65rem 0.75rem;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
background: var(--vp-c-bg);
|
||||
margin-bottom: 0.8rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.switch-container {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.switch-area {
|
||||
background: var(--vp-c-bg);
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.switch-area:hover {
|
||||
border-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.transistor-symbol {
|
||||
width: 120px;
|
||||
height: 80px;
|
||||
margin: 0 auto 0.5rem;
|
||||
}
|
||||
|
||||
.transistor-svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.switch-label {
|
||||
.control-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
align-items: center;
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
.state-label {
|
||||
.control-label {
|
||||
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;
|
||||
font-size: 1.1rem;
|
||||
color: var(--vp-c-brand);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.current-flow {
|
||||
.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-3);
|
||||
opacity: 0.5;
|
||||
transition: all 0.3s;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.current-flow.active {
|
||||
opacity: 1;
|
||||
color: var(--vp-c-success);
|
||||
.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;
|
||||
}
|
||||
|
||||
.channel-track {
|
||||
height: 2.4rem;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
border-radius: 999px;
|
||||
background: #e5e7eb;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.channel-track.on {
|
||||
background: var(--vp-c-success-soft);
|
||||
border-color: var(--vp-c-success);
|
||||
}
|
||||
|
||||
.block-icon {
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
.flow-dot {
|
||||
width: 0.42rem;
|
||||
height: 0.42rem;
|
||||
border-radius: 50%;
|
||||
background: var(--vp-c-success);
|
||||
position: absolute;
|
||||
left: -8%;
|
||||
animation: flow 1.5s linear infinite;
|
||||
}
|
||||
|
||||
.flow-dot.d2 {
|
||||
animation-delay: 0.45s;
|
||||
}
|
||||
|
||||
.flow-dot.d3 {
|
||||
animation-delay: 0.9s;
|
||||
}
|
||||
|
||||
@keyframes flow {
|
||||
from {
|
||||
left: -8%;
|
||||
}
|
||||
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 {
|
||||
flex: 1;
|
||||
min-width: 250px;
|
||||
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.5rem;
|
||||
margin-bottom: 0.55rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
|
||||
th, td {
|
||||
th,
|
||||
td {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
padding: 0.5rem;
|
||||
padding: 0.45rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -248,6 +352,27 @@ 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;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background: var(--vp-c-bg-alt);
|
||||
padding: 0.75rem;
|
||||
@@ -259,4 +384,18 @@ tr.highlight {
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.info-box strong {
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 860px) {
|
||||
.demo-content {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.step-guide {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+681
-377
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user