Files
test-repo/docs/.vitepress/theme/components/appendix/computer-fundamentals/OSArchitectureDemo.vue
T
2026-02-24 00:18:09 +08:00

318 lines
6.7 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="demo">
<div class="scene">
<!-- 应用程序层 -->
<div class="layer-box app-layer" :class="{ active: currentStep >= 1 }">
<div class="layer-title">📱 应用程序</div>
<div class="apps">
<span class="app-icon" :class="{ pulse: currentStep === 1 }">🎵</span>
<span class="app-icon" :class="{ pulse: currentStep === 1 }">💬</span>
<span class="app-icon" :class="{ pulse: currentStep === 1 }">🎮</span>
</div>
</div>
<!-- 流动箭头 -->
<div class="flow-arrow" :class="{ flowing: currentStep === 2 }">
<div class="arrow-line"></div>
<div class="arrow-head"></div>
<div class="packet" v-if="currentStep === 2">📦 请求</div>
</div>
<!-- 操作系统层 -->
<div class="layer-box os-layer" :class="{ active: currentStep >= 2, processing: currentStep === 3 }">
<div class="layer-title">🖥 操作系统</div>
<div class="os-core">
<div class="core-item" :class="{ working: currentStep === 3 && subStep === 0 }">调度CPU</div>
<div class="core-item" :class="{ working: currentStep === 3 && subStep === 1 }">分配内存</div>
<div class="core-item" :class="{ working: currentStep === 3 && subStep === 2 }">管理文件</div>
</div>
</div>
<!-- 流动箭头 -->
<div class="flow-arrow" :class="{ flowing: currentStep === 4 }">
<div class="arrow-line"></div>
<div class="arrow-head"></div>
<div class="packet" v-if="currentStep === 4"> 指令</div>
</div>
<!-- 硬件层 -->
<div class="layer-box hw-layer" :class="{ active: currentStep >= 4, working: currentStep === 5 }">
<div class="layer-title">💾 硬件</div>
<div class="hw-items">
<span class="hw-icon" :class="{ spin: currentStep === 5 }">🧠 CPU</span>
<span class="hw-icon" :class="{ flash: currentStep === 5 }">💾 内存</span>
<span class="hw-icon" :class="{ flash: currentStep === 5 }">💿 硬盘</span>
</div>
</div>
</div>
<div class="status-bar">
<span class="status-text">{{ statusText }}</span>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'
const currentStep = ref(0)
const subStep = ref(0)
let timer = null
const statusTexts = [
'应用程序准备发起请求...',
'应用程序:我要播放音乐!',
'请求发送给操作系统...',
'操作系统正在协调资源...',
'指令下发到硬件...',
'硬件开始执行:音乐播放中 🎵'
]
const statusText = computed(() => statusTexts[currentStep.value] || '')
const nextStep = () => {
if (currentStep.value === 3) {
// 在操作系统处理阶段,循环显示子步骤
subStep.value = (subStep.value + 1) % 3
if (subStep.value === 0) {
currentStep.value = 4
}
} else {
currentStep.value = (currentStep.value + 1) % 6
if (currentStep.value === 3) {
subStep.value = 0
}
}
}
onMounted(() => {
timer = setInterval(nextStep, 1500)
})
onUnmounted(() => {
clearInterval(timer)
})
</script>
<style scoped>
.demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 16px;
margin: 1rem 0;
}
.scene {
display: flex;
flex-direction: column;
gap: 8px;
}
.layer-box {
padding: 12px;
border-radius: 8px;
border: 2px solid transparent;
transition: all 0.3s;
opacity: 0.5;
}
.layer-box.active {
opacity: 1;
}
.app-layer {
background: linear-gradient(135deg, #667eea22, #764ba222);
border-color: #667eea55;
}
.app-layer.active {
border-color: #667eea;
box-shadow: 0 0 15px #667eea55;
}
.os-layer {
background: linear-gradient(135deg, #f093fb22, #f5576c22);
border-color: #f5576c55;
}
.os-layer.active {
border-color: #f5576c;
box-shadow: 0 0 15px #f5576c55;
}
.os-layer.processing {
animation: pulse-os 1s infinite;
}
.hw-layer {
background: linear-gradient(135deg, #4facfe22, #00f2fe22);
border-color: #4facfe55;
}
.hw-layer.active {
border-color: #4facfe;
box-shadow: 0 0 15px #4facfe55;
}
.hw-layer.working {
animation: pulse-hw 0.5s infinite;
}
.layer-title {
font-weight: 600;
font-size: 13px;
margin-bottom: 8px;
text-align: center;
}
.apps {
display: flex;
justify-content: center;
gap: 16px;
}
.app-icon {
font-size: 24px;
transition: transform 0.3s;
}
.app-icon.pulse {
animation: bounce 0.5s infinite;
}
.os-core {
display: flex;
justify-content: center;
gap: 8px;
flex-wrap: wrap;
}
.core-item {
padding: 6px 12px;
background: var(--vp-c-bg);
border-radius: 4px;
font-size: 11px;
transition: all 0.3s;
}
.core-item.working {
background: #f5576c;
color: white;
transform: scale(1.1);
}
.hw-items {
display: flex;
justify-content: center;
gap: 12px;
flex-wrap: wrap;
}
.hw-icon {
font-size: 12px;
padding: 4px 8px;
background: var(--vp-c-bg);
border-radius: 4px;
transition: all 0.3s;
}
.hw-icon.spin {
animation: spin 1s linear infinite;
}
.hw-icon.flash {
animation: flash 0.5s infinite;
}
.flow-arrow {
display: flex;
flex-direction: column;
align-items: center;
height: 30px;
position: relative;
}
.arrow-line {
width: 2px;
height: 20px;
background: var(--vp-c-divider);
transition: all 0.3s;
}
.flow-arrow.flowing .arrow-line {
background: linear-gradient(to bottom, #f5576c, #4facfe);
box-shadow: 0 0 5px #f5576c;
}
.arrow-head {
font-size: 10px;
color: var(--vp-c-divider);
line-height: 1;
}
.flow-arrow.flowing .arrow-head {
color: #4facfe;
}
.packet {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #f5576c;
color: white;
padding: 2px 8px;
border-radius: 4px;
font-size: 10px;
font-weight: 600;
animation: flow-down 1s ease-in-out;
white-space: nowrap;
}
.status-bar {
margin-top: 12px;
padding: 8px 12px;
background: var(--vp-c-bg);
border-radius: 6px;
text-align: center;
}
.status-text {
font-size: 12px;
color: var(--vp-c-text-2);
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
@keyframes pulse-os {
0%, 100% { box-shadow: 0 0 5px #f5576c55; }
50% { box-shadow: 0 0 20px #f5576caa; }
}
@keyframes pulse-hw {
0%, 100% { box-shadow: 0 0 5px #4facfe55; }
50% { box-shadow: 0 0 20px #4facfeaa; }
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes flash {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
@keyframes flow-down {
0% { opacity: 0; transform: translate(-50%, -100%); }
20% { opacity: 1; }
80% { opacity: 1; }
100% { opacity: 0; transform: translate(-50%, 0%); }
}
</style>