c238f07e0d
Add a comprehensive terminal introduction guide with interactive Vue components demonstrating terminal concepts. Includes: - Terminal definition and architecture visualization - Character grid and cell inspector - ANSI escape sequences demo - Input visualization and signal mechanisms - Flow diagrams and TUI examples The components are registered in the VitePress theme and linked from the appendix section. Each component includes detailed documentation and interactive elements to help users understand terminal principles.
240 lines
5.3 KiB
Vue
240 lines
5.3 KiB
Vue
<!--
|
||
CellInspector.vue
|
||
单元格检查器组件
|
||
|
||
用途:
|
||
深入展示单个终端单元格(Cell)的内部结构。
|
||
说明一个单元格不仅仅包含字符,还包含前景色、背景色、加粗、下划线等属性。
|
||
|
||
交互功能:
|
||
- 属性切换:用户可以修改字符、颜色和样式。
|
||
- 实时预览:左侧大图实时反映右侧属性的修改结果。
|
||
-->
|
||
<template>
|
||
<div class="cell-inspector">
|
||
<div class="preview-area">
|
||
<div class="large-cell" :style="cellStyle">
|
||
{{ char }}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="controls-area">
|
||
<div class="control-group">
|
||
<label>CHARACTER</label>
|
||
<div class="char-buttons">
|
||
<button
|
||
v-for="c in chars"
|
||
:key="c"
|
||
:class="{ active: char === c }"
|
||
@click="char = c"
|
||
>{{ c }}</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-group">
|
||
<label>FOREGROUND</label>
|
||
<div class="color-palette">
|
||
<div
|
||
v-for="color in colors"
|
||
:key="color"
|
||
class="color-swatch"
|
||
:style="{ backgroundColor: color }"
|
||
:class="{ active: fgColor === color }"
|
||
@click="fgColor = color"
|
||
></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-group">
|
||
<label>BACKGROUND</label>
|
||
<div class="color-palette">
|
||
<div
|
||
class="color-swatch"
|
||
:class="{ active: bgColor === 'transparent' }"
|
||
style="background: linear-gradient(45deg, #222 25%, transparent 25%), linear-gradient(-45deg, #222 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #222 75%), linear-gradient(-45deg, transparent 75%, #222 75%); background-size: 10px 10px; background-color: #111;"
|
||
@click="bgColor = 'transparent'"
|
||
></div>
|
||
<div
|
||
v-for="color in bgColors"
|
||
:key="color"
|
||
class="color-swatch"
|
||
:style="{ backgroundColor: color }"
|
||
:class="{ active: bgColor === color }"
|
||
@click="bgColor = color"
|
||
></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-group">
|
||
<label>ATTRIBUTES</label>
|
||
<div class="toggles">
|
||
<label class="toggle">
|
||
<input type="checkbox" v-model="isBold">
|
||
<span>Bold</span>
|
||
</label>
|
||
<label class="toggle">
|
||
<input type="checkbox" v-model="isUnderline">
|
||
<span>Underline</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed } from 'vue'
|
||
|
||
const chars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P']
|
||
const colors = [
|
||
'#ef4444', '#22c55e', '#eab308', '#3b82f6', '#a855f7', '#06b6d4', '#f3f4f6', '#6b7280',
|
||
'#f87171', '#4ade80', '#facc15', '#60a5fa', '#c084fc', '#22d3ee', '#ffffff'
|
||
]
|
||
const bgColors = [
|
||
'#000000', '#1f2937', '#111827', '#374151', '#1e3a8a', '#3f2c08', '#310b0b'
|
||
]
|
||
|
||
const char = ref('A')
|
||
const fgColor = ref('#22c55e')
|
||
const bgColor = ref('transparent')
|
||
const isBold = ref(false)
|
||
const isUnderline = ref(false)
|
||
|
||
const cellStyle = computed(() => ({
|
||
color: fgColor.value,
|
||
backgroundColor: bgColor.value,
|
||
fontWeight: isBold.value ? 'bold' : 'normal',
|
||
textDecoration: isUnderline.value ? 'underline' : 'none'
|
||
}))
|
||
</script>
|
||
|
||
<style scoped>
|
||
.cell-inspector {
|
||
display: grid;
|
||
grid-template-columns: 200px 1fr;
|
||
gap: 40px;
|
||
background: #09090b;
|
||
padding: 30px;
|
||
border-radius: 12px;
|
||
border: 1px solid #27272a;
|
||
font-family: 'JetBrains Mono', 'Menlo', monospace;
|
||
}
|
||
|
||
.preview-area {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border: 1px solid #27272a;
|
||
border-radius: 8px;
|
||
background: #000;
|
||
aspect-ratio: 3/4;
|
||
}
|
||
|
||
.large-cell {
|
||
font-size: 120px;
|
||
line-height: 1;
|
||
width: 140px;
|
||
height: 180px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.controls-area {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24px;
|
||
}
|
||
|
||
.control-group label {
|
||
display: block;
|
||
color: #a1a1aa; /* Zinc 400 */
|
||
font-size: 12px;
|
||
margin-bottom: 10px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 1px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.char-buttons {
|
||
display: grid;
|
||
grid-template-columns: repeat(8, 1fr);
|
||
gap: 6px;
|
||
}
|
||
|
||
.char-buttons button {
|
||
background: #18181b;
|
||
border: 1px solid #27272a;
|
||
color: #a1a1aa;
|
||
padding: 8px 0;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.char-buttons button:hover {
|
||
border-color: #52525b;
|
||
color: #fff;
|
||
background: #27272a;
|
||
}
|
||
|
||
.char-buttons button.active {
|
||
background: #fff;
|
||
color: #000;
|
||
border-color: #fff;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.color-palette {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
}
|
||
|
||
.color-swatch {
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
border: 2px solid transparent;
|
||
transition: transform 0.1s;
|
||
}
|
||
|
||
.color-swatch:hover {
|
||
transform: scale(1.1);
|
||
}
|
||
|
||
.color-swatch.active {
|
||
border-color: #fff;
|
||
transform: scale(1.1);
|
||
box-shadow: 0 0 10px rgba(0,0,0,0.5);
|
||
}
|
||
|
||
.toggles {
|
||
display: flex;
|
||
gap: 20px;
|
||
}
|
||
|
||
.toggle {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
color: #e4e4e7;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
}
|
||
|
||
.toggle input {
|
||
width: 16px;
|
||
height: 16px;
|
||
accent-color: #22c55e;
|
||
}
|
||
|
||
@media (max-width: 640px) {
|
||
.cell-inspector {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
</style>
|