refactor: 重构 api-intro、api-design、transistor-to-cpu 组件为紧凑布局

- 重构 api-intro 7 个 Vue 组件为更紧凑的左右布局
- 重构 api-design 相关组件
- 重构 transistor-to-cpu 相关组件
- 统一使用 demo-root -> demo-header -> demo-layout -> info-box 结构
- 扩写文章内容为 MIT 讲义风格
This commit is contained in:
sanbuphy
2026-02-23 01:50:43 +08:00
parent 2a0fdd3392
commit 1062e2e16f
68 changed files with 4455 additions and 3469 deletions
@@ -1,422 +1,242 @@
<!--
ApiMethodDemo.vue
目标清晰展示各种 HTTP 方法的含义和使用场景
ApiMethodDemo.vue - 紧凑版
目标展示 HTTP 方法的语义
-->
<template>
<div class="demo">
<div class="title">
🔍 HTTP 方法GETPOSTPUTDELETE 是什么
<div class="demo-root">
<div class="demo-header">
<span class="icon">📋</span>
<span class="title">HTTP 方法告诉服务器你想做什么</span>
</div>
<p class="subtitle">
把它们想象成对数据的"操作方式"
</p>
<div class="methods-grid">
<div class="method-card get">
<div class="method-badge">
GET
</div>
<div class="method-title">
📖 获取查询
</div>
<div class="method-desc">
<p><strong>只看不改</strong> - 从服务器获取数据</p>
<div class="method-examples">
<div class="example-item">
查询用户信息
</div>
<div class="example-item">
搜索商品
</div>
<div class="example-item">
获取文章列表
</div>
<div class="demo-layout">
<div class="methods-grid">
<div
v-for="m in methods"
:key="m.name"
class="method-card"
:class="{ active: selected === m.name }"
@click="selected = m.name"
>
<div class="m-badge" :class="m.color">
{{ m.name }}
</div>
<div class="m-desc">
{{ m.desc }}
</div>
<div class="m-example">
{{ m.example }}
</div>
</div>
<div class="method-tip">
💡 可以安全重试不会改变服务器数据
</div>
</div>
<div class="method-card post">
<div class="method-badge">
POST
<div class="right-panel">
<div class="compare-header">对比幂等性</div>
<div class="compare-row">
<span class="c-label">GET</span>
<span class="c-val">查询10次 = 查询1次 </span>
</div>
<div class="method-title">
创建新增
<div class="compare-row">
<span class="c-label">DELETE</span>
<span class="c-val">删除10次 = 删除1次 </span>
</div>
<div class="method-desc">
<p><strong>新建数据</strong> - 在服务器创建新资源</p>
<div class="method-examples">
<div class="example-item">
创建新用户
</div>
<div class="example-item">
提交订单
</div>
<div class="example-item">
发表评论
</div>
</div>
</div>
<div class="method-tip">
不能随意重试可能会重复创建
</div>
</div>
<div class="method-card put">
<div class="method-badge">
PUT
</div>
<div class="method-title">
更新替换
</div>
<div class="method-desc">
<p><strong>整体替换</strong> - 用新数据完全替换旧数据</p>
<div class="method-examples">
<div class="example-item">
修改用户全部信息
</div>
<div class="example-item">
更换文章全部内容
</div>
</div>
</div>
<div class="method-tip">
会覆盖整个资源需要提供完整数据
</div>
</div>
<div class="method-card patch">
<div class="method-badge">
PATCH
</div>
<div class="method-title">
🔧 修改部分
</div>
<div class="method-desc">
<p><strong>局部更新</strong> - 只修改资源的部分字段</p>
<div class="method-examples">
<div class="example-item">
只修改用户昵称
</div>
<div class="example-item">
更新文章标题
</div>
</div>
</div>
<div class="method-tip">
💡 只传需要修改的字段更灵活
</div>
</div>
<div class="method-card delete">
<div class="method-badge">
DELETE
</div>
<div class="method-title">
🗑 删除
</div>
<div class="method-desc">
<p><strong>移除数据</strong> - 从服务器删除资源</p>
<div class="method-examples">
<div class="example-item">
删除用户
</div>
<div class="example-item">
取消订单
</div>
<div class="example-item">
删除评论
</div>
</div>
</div>
<div class="method-tip">
操作不可逆删除后无法恢复
<div class="compare-row warn">
<span class="c-label">POST</span>
<span class="c-val">下单10次 = 10个订单 </span>
</div>
</div>
</div>
<div class="comparison-table">
<div class="table-title">
📊 快速对比
</div>
<table>
<thead>
<tr>
<th>方法</th>
<th>操作</th>
<th>是否会改数据</th>
<th>能否重试</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="badge get">GET</span></td>
<td>查询</td>
<td> </td>
<td> 可以</td>
</tr>
<tr>
<td><span class="badge post">POST</span></td>
<td>创建</td>
<td> </td>
<td> 不建议</td>
</tr>
<tr>
<td><span class="badge put">PUT</span></td>
<td>替换</td>
<td> </td>
<td> 不建议</td>
</tr>
<tr>
<td><span class="badge patch">PATCH</span></td>
<td>修改</td>
<td> </td>
<td> 不建议</td>
</tr>
<tr>
<td><span class="badge delete">DELETE</span></td>
<td>删除</td>
<td> </td>
<td> 不建议</td>
</tr>
</tbody>
</table>
</div>
<div class="tips">
<p><strong>💡 新手建议</strong></p>
<ul>
<li>
先学会 <strong>GET</strong>查询
<strong>POST</strong>创建就够用了
</li>
<li>PUT/PATCH/DELETE 可以慢慢学理解原理更重要</li>
<li>实际开发中GET POST 占了 80% 的使用场景</li>
</ul>
<div class="info-box">
<strong>核心思想</strong>
<span
>HTTP 方法就是动词GET "问"POST "做"PUT/PATCH "改"DELETE
"删"</span
>
</div>
</div>
</template>
<script setup>
// 无需脚本逻辑
import { ref } from 'vue'
const selected = ref('GET')
const methods = [
{ name: 'GET', desc: '获取数据', example: 'GET /users', color: 'green' },
{ name: 'POST', desc: '创建数据', example: 'POST /users', color: 'blue' },
{ name: 'PUT', desc: '替换数据', example: 'PUT /users/1', color: 'orange' },
{
name: 'PATCH',
desc: '部分修改',
example: 'PATCH /users/1',
color: 'yellow'
},
{ name: 'DELETE', desc: '删除数据', example: 'DELETE /users/1', color: 'red' }
]
</script>
<style scoped>
.demo {
.demo-root {
border: 1px solid var(--vp-c-divider);
border-radius: 12px;
padding: 20px;
border-radius: 10px;
overflow: hidden;
background: var(--vp-c-bg-soft);
margin: 16px 0;
margin: 1rem 0;
font-size: 0.85rem;
}
.title {
.demo-header {
padding: 10px 16px;
background: var(--vp-c-bg);
border-bottom: 1px solid var(--vp-c-divider);
display: flex;
align-items: center;
gap: 8px;
}
.icon {
font-size: 18px;
font-weight: bold;
margin-bottom: 8px;
color: var(--vp-c-text-1);
}
.title {
font-weight: 600;
font-size: 0.9rem;
}
.subtitle {
color: var(--vp-c-text-2);
margin-bottom: 24px;
.demo-layout {
display: flex;
}
.methods-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 16px;
margin-bottom: 24px;
flex: 1;
display: flex;
gap: 8px;
padding: 12px;
overflow-x: auto;
}
.right-panel {
width: 200px;
padding: 12px;
background: var(--vp-c-bg);
border-left: 1px solid var(--vp-c-divider);
}
@media (max-width: 640px) {
.demo-layout {
flex-direction: column;
}
.methods-grid {
flex-wrap: wrap;
}
.right-panel {
width: 100%;
border-left: none;
border-top: 1px solid var(--vp-c-divider);
}
}
.method-card {
flex: 1;
min-width: 100px;
padding: 10px;
background: var(--vp-c-bg);
border: 2px solid var(--vp-c-divider);
border-radius: 12px;
padding: 16px;
position: relative;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
}
.method-card.get {
border-color: #3b82f6;
}
.method-card.post {
border-color: #22c55e;
}
.method-card.put {
border-color: #f59e0b;
}
.method-card.patch {
border-color: #8b5cf6;
}
.method-card.delete {
border-color: #ef4444;
}
.method-badge {
position: absolute;
top: 12px;
right: 12px;
padding: 4px 12px;
border-radius: 6px;
font-weight: bold;
font-size: 12px;
color: white;
}
.method-card.get .method-badge {
background: #3b82f6;
}
.method-card.post .method-badge {
background: #22c55e;
}
.method-card.put .method-badge {
background: #f59e0b;
}
.method-card.patch .method-badge {
background: #8b5cf6;
}
.method-card.delete .method-badge {
background: #ef4444;
}
.method-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
padding-right: 60px;
color: var(--vp-c-text-1);
}
.method-desc p {
margin: 0 0 12px 0;
font-size: 14px;
font-weight: 600;
}
.method-examples {
.method-card.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-soft);
padding: 12px;
border-radius: 6px;
margin-bottom: 12px;
}
.example-item {
font-size: 13px;
padding: 4px 0;
color: var(--vp-c-text-1);
.m-badge {
display: inline-block;
padding: 3px 8px;
border-radius: 4px;
font-size: 0.75rem;
font-weight: bold;
margin-bottom: 6px;
}
.method-tip {
padding: 10px 12px;
border-radius: 6px;
font-size: 12px;
line-height: 1.5;
.m-badge.green {
background: #dcfce7;
color: #166534;
}
.method-card.get .method-tip {
background: #eff6ff;
.m-badge.blue {
background: #dbeafe;
color: #1e40af;
}
.method-card.post .method-tip,
.method-card.put .method-tip,
.method-card.patch .method-tip,
.method-card.delete .method-tip {
background: #fef2f2;
.m-badge.orange {
background: #ffedd5;
color: #9a3412;
}
.m-badge.yellow {
background: #fef9c3;
color: #854d0e;
}
.m-badge.red {
background: #fee2e2;
color: #991b1b;
}
.comparison-table {
background: var(--vp-c-bg);
border: 2px solid var(--vp-c-divider);
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
.m-desc {
font-size: 0.8rem;
font-weight: 600;
margin-bottom: 4px;
}
.table-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 16px;
color: var(--vp-c-text-1);
.m-example {
font-family: monospace;
font-size: 0.7rem;
color: var(--vp-c-text-3);
}
table {
width: 100%;
border-collapse: collapse;
}
thead {
background: var(--vp-c-bg-soft);
}
th {
padding: 12px;
text-align: left;
font-weight: bold;
font-size: 13px;
color: var(--vp-c-text-1);
border-bottom: 2px solid var(--vp-c-divider);
}
td {
padding: 12px;
font-size: 13px;
border-bottom: 1px solid var(--vp-c-divider);
color: var(--vp-c-text-1);
}
tr:last-child td {
border-bottom: none;
}
.badge {
display: inline-block;
padding: 4px 10px;
border-radius: 6px;
font-weight: bold;
font-size: 12px;
color: white;
}
.badge.get {
background: #3b82f6;
}
.badge.post {
background: #22c55e;
}
.badge.put {
background: #f59e0b;
}
.badge.patch {
background: #8b5cf6;
}
.badge.delete {
background: #ef4444;
}
.tips {
background: var(--vp-c-bg);
padding: 16px;
border-radius: 6px;
font-size: 14px;
line-height: 1.8;
.compare-header {
font-size: 0.8rem;
font-weight: 600;
margin-bottom: 8px;
color: var(--vp-c-text-2);
}
.tips p {
margin-bottom: 8px;
.compare-row {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 8px;
background: var(--vp-c-bg-soft);
border-radius: 4px;
margin-bottom: 6px;
font-size: 0.75rem;
}
.tips ul {
margin: 0;
padding-left: 20px;
.compare-row.warn {
background: #fef2f2;
}
.tips li {
margin: 4px 0;
.c-label {
font-weight: bold;
min-width: 50px;
}
.c-val {
color: var(--vp-c-text-2);
}
.info-box {
display: flex;
gap: 0.25rem;
padding: 10px 14px;
background: var(--vp-c-bg-alt);
border-top: 1px solid var(--vp-c-divider);
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.info-box strong {
white-space: nowrap;
flex-shrink: 0;
}
</style>