feat: update documentation and component demos for backend layered architecture
- Add new LanguageScopeDemo component for backend languages overview - Refactor and simplify existing demo components (ControllerLayerDemo, DtoFlowDemo, DependencyDirectionDemo) - Update .gitignore to exclude .claude/skills directory - Modify backend-related sections in documentation from "后端与全栈" to "后端开发" - Add new backend layered architecture demo components (CleanArchitectureDemo, DependencyDirectionDemo) - Improve documentation structure and content for stage-3 core skills - Fix component initialization timing in CompileVsInterpretDemo and RateLimiterDemo - Add design style prompt reference in frontend documentation
This commit is contained in:
+50
-308
@@ -1,341 +1,83 @@
|
||||
<template>
|
||||
<div class="dependency-direction-demo">
|
||||
<div class="demo-header">
|
||||
<h4>🔄 依赖方向:分层架构的核心规则</h4>
|
||||
<p class="subtitle">
|
||||
理解依赖方向,才能真正掌握分层架构
|
||||
</p>
|
||||
<div class="dep-demo">
|
||||
<div class="header">
|
||||
<div class="title">依赖方向:分层架构的核心规则</div>
|
||||
<div class="subtitle">理解依赖方向,才能真正掌握分层架构</div>
|
||||
</div>
|
||||
|
||||
<!-- 依赖方向可视化 -->
|
||||
<div class="direction-visualization">
|
||||
<div class="arch-diagram">
|
||||
<!-- 外层 -->
|
||||
<div class="content-box">
|
||||
<div class="layers">
|
||||
<div class="layer outer">
|
||||
<div class="layer-label">
|
||||
外层(UI / 外部系统)
|
||||
</div>
|
||||
<div class="layer-box">
|
||||
Controller
|
||||
</div>
|
||||
<div class="layer-label">外层(UI / 外部系统)</div>
|
||||
<div class="layer-box">Controller</div>
|
||||
</div>
|
||||
|
||||
<!-- 依赖箭头 -->
|
||||
<div class="dependency-arrow down">
|
||||
<span class="arrow-line" />
|
||||
<span class="arrow-head">▶️ 依赖</span>
|
||||
</div>
|
||||
|
||||
<!-- 中层 -->
|
||||
<div class="dep-arrow">↓ 依赖</div>
|
||||
<div class="layer middle">
|
||||
<div class="layer-label">
|
||||
中层(应用层)
|
||||
</div>
|
||||
<div class="layer-box">
|
||||
Service
|
||||
</div>
|
||||
<div class="layer-label">中层(应用层)</div>
|
||||
<div class="layer-box">Service</div>
|
||||
</div>
|
||||
|
||||
<!-- 依赖箭头 -->
|
||||
<div class="dependency-arrow down">
|
||||
<span class="arrow-line" />
|
||||
<span class="arrow-head">▶️ 依赖</span>
|
||||
</div>
|
||||
|
||||
<!-- 内层 -->
|
||||
<div class="dep-arrow">↓ 依赖</div>
|
||||
<div class="layer inner">
|
||||
<div class="layer-label">
|
||||
内层(领域层)
|
||||
</div>
|
||||
<div class="layer-box">
|
||||
Domain / Repository
|
||||
</div>
|
||||
<div class="layer-label">内层(领域层)</div>
|
||||
<div class="layer-box">Domain / Repository</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 核心原则说明 -->
|
||||
<div class="principle-box">
|
||||
<div class="principle-title">
|
||||
🎯 核心原则:依赖倒置(DIP)
|
||||
</div>
|
||||
<div class="principle-content">
|
||||
<p><strong>上层模块不应该依赖下层模块的具体实现,而应该依赖于抽象。</strong></p>
|
||||
<div class="rule-list">
|
||||
<div class="rule-item">
|
||||
<span class="rule-icon">✅</span>
|
||||
<div class="rule-text">
|
||||
<strong>Controller → Service 接口</strong>
|
||||
<div class="rule-desc">
|
||||
Controller 只依赖 Service 的接口,不依赖实现类
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rule-item">
|
||||
<span class="rule-icon">✅</span>
|
||||
<div class="rule-text">
|
||||
<strong>Service → Repository 接口</strong>
|
||||
<div class="rule-desc">
|
||||
Service 只依赖 Repository 接口,不关心数据怎么存
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rule-item">
|
||||
<span class="rule-icon">✅</span>
|
||||
<div class="rule-text">
|
||||
<strong>所有层依赖 Domain</strong>
|
||||
<div class="rule-desc">
|
||||
Domain 是核心,被所有上层依赖,但 Domain 不依赖任何层
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-title">核心原则:依赖倒置(DIP)</div>
|
||||
<p>上层模块不应该依赖下层模块的具体实现,而应该依赖于抽象。</p>
|
||||
<div class="rules">
|
||||
<div v-for="r in rules" :key="r.title" class="rule">
|
||||
<strong>{{ r.title }}</strong>
|
||||
<div class="rule-desc">{{ r.desc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 依赖方向示意图 -->
|
||||
<div class="direction-diagram">
|
||||
<h5>📊 依赖方向示意图</h5>
|
||||
<div class="diagram-content">
|
||||
<pre class="diagram-code">
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Controller Layer │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ UserController │ │
|
||||
│ │ - @Autowired private IUserService userService; │ │
|
||||
│ │ ✅ 依赖接口,不依赖实现 │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ 依赖(Dependency) │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ Service Layer │ │
|
||||
│ │ ┌────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ UserServiceImpl │ │ │
|
||||
│ │ │ - @Autowired private UserRepository repository; │ │ │
|
||||
│ │ │ ✅ 依赖 Repository 接口 │ │ │
|
||||
│ │ └────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ▼ 依赖 │ │
|
||||
│ │ ┌────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Repository Layer │ │ │
|
||||
│ │ │ ┌──────────────────────────────────────────┐ │ │ │
|
||||
│ │ │ │ UserRepository │ │ │ │
|
||||
│ │ │ │ - extends JpaRepository<User, Long> │ │ │ │
|
||||
│ │ │ └──────────────────────────────────────────┘ │ │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ │ ▼ 依赖 │ │ │
|
||||
│ │ │ ┌──────────────────────────────────────────┐ │ │ │
|
||||
│ │ │ │ Domain Layer (核心领域) │ │ │ │
|
||||
│ │ │ │ ┌────────────────────────────────────┐ │ │ │ │
|
||||
│ │ │ │ │ User (Entity) │ │ │ │ │
|
||||
│ │ │ │ │ - 不包含任何层依赖 │ │ │ │ │
|
||||
│ │ │ │ │ - 被所有层依赖 │ │ │ │ │
|
||||
│ │ │ │ └────────────────────────────────────┘ │ │ │ │
|
||||
│ │ │ └──────────────────────────────────────────┘ │ │ │
|
||||
│ │ └────────────────────────────────────────────────┘ │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// Component logic can be added here if needed
|
||||
const rules = [
|
||||
{ title: 'Controller → Service 接口', desc: 'Controller 只依赖 Service 的接口,不依赖实现类' },
|
||||
{ title: 'Service → Repository 接口', desc: 'Service 只依赖 Repository 接口,不关心数据怎么存' },
|
||||
{ title: '所有层依赖 Domain', desc: 'Domain 是核心,被所有上层依赖,但 Domain 不依赖任何层' }
|
||||
]
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dependency-direction-demo {
|
||||
padding: 24px;
|
||||
background: linear-gradient(135deg, #f0f7ff 0%, #e6f0ff 100%);
|
||||
border-radius: 12px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
}
|
||||
.dep-demo { padding: 20px; background: var(--vp-c-bg-soft); border-radius: 12px; }
|
||||
.header { text-align: center; margin-bottom: 20px; }
|
||||
.title { font-size: 16px; font-weight: 600; color: var(--vp-c-text-1); }
|
||||
.subtitle { font-size: 13px; color: var(--vp-c-text-3); margin-top: 4px; }
|
||||
|
||||
.demo-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
.content-box {
|
||||
padding: 18px; border-radius: 10px;
|
||||
background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.demo-header h4 {
|
||||
margin: 0 0 8px 0;
|
||||
color: #1a1a2e;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
margin: 0;
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.direction-visualization {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
margin-bottom: 24px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.arch-diagram {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.layer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.layer-label {
|
||||
font-size: 11px;
|
||||
color: #909399;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.layers { display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px; }
|
||||
.layer-label { font-size: 11px; color: var(--vp-c-text-3); margin-bottom: 4px; }
|
||||
.layer-box {
|
||||
padding: 16px 20px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 6px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
text-align: center;
|
||||
border-left: 4px solid #409eff;
|
||||
}
|
||||
|
||||
.layer.outer .layer-box {
|
||||
border-left-color: #67c23a;
|
||||
}
|
||||
|
||||
.layer.middle .layer-box {
|
||||
border-left-color: #e6a23c;
|
||||
}
|
||||
|
||||
.layer.inner .layer-box {
|
||||
border-left-color: #409eff;
|
||||
}
|
||||
|
||||
.dependency-arrow {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.arrow-line {
|
||||
width: 2px;
|
||||
height: 12px;
|
||||
background: #dcdfe6;
|
||||
}
|
||||
|
||||
.arrow-head {
|
||||
color: #909399;
|
||||
font-size: 11px;
|
||||
margin-top: 2px;
|
||||
padding: 14px; border-radius: 6px; text-align: center;
|
||||
font-weight: 500; color: var(--vp-c-text-1);
|
||||
background: var(--vp-c-bg-soft); border-left: 3px solid var(--vp-c-divider);
|
||||
}
|
||||
.layer.outer .layer-box { border-left-color: #10b981; }
|
||||
.layer.middle .layer-box { border-left-color: #f59e0b; }
|
||||
.layer.inner .layer-box { border-left-color: #3b82f6; }
|
||||
.dep-arrow { text-align: center; color: var(--vp-c-text-3); font-size: 12px; }
|
||||
|
||||
.principle-box {
|
||||
background: linear-gradient(135deg, #e6f7ff 0%, #f0f7ff 100%);
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
border-left: 4px solid #1890ff;
|
||||
padding: 16px; border-radius: 8px;
|
||||
background: var(--vp-c-brand-soft); border-left: 3px solid var(--vp-c-brand-1);
|
||||
}
|
||||
.p-title { font-size: 14px; font-weight: 600; color: var(--vp-c-text-1); margin-bottom: 8px; }
|
||||
.principle-box p { margin: 0 0 12px; font-size: 13px; color: var(--vp-c-text-2); line-height: 1.6; }
|
||||
|
||||
.principle-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #1a1a2e;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.principle-content p {
|
||||
margin: 0 0 12px 0;
|
||||
color: #595959;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.rule-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.rule-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.rule-icon {
|
||||
font-size: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.rule-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.rule-text strong {
|
||||
color: #1a1a2e;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.rule-desc {
|
||||
color: #8c8c8c;
|
||||
font-size: 12px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.direction-diagram {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.direction-diagram h5 {
|
||||
margin: 0 0 16px 0;
|
||||
color: #1a1a2e;
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.diagram-content {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.diagram-code {
|
||||
font-family: 'Monaco', 'Menlo', monospace;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
color: #595959;
|
||||
margin: 0;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.model-cards {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.comparison-tabs {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tab-btn {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.rules { display: flex; flex-direction: column; gap: 8px; }
|
||||
.rule {
|
||||
padding: 10px; border-radius: 6px;
|
||||
background: var(--vp-c-bg); font-size: 13px; color: var(--vp-c-text-1);
|
||||
}
|
||||
.rule-desc { font-size: 12px; color: var(--vp-c-text-3); margin-top: 2px; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user