From d35211071a14dbdabcdcd83977964999eed5f70a Mon Sep 17 00:00:00 2001 From: sanbuphy Date: Sat, 14 Feb 2026 20:23:34 +0800 Subject: [PATCH] style: update border-radius and padding values across components - standardize border-radius from 8px to 6px for consistent styling - adjust padding values from 1rem to 0.75rem for better visual hierarchy - remove redundant overflow-y properties for cleaner code --- .../agent-intro/AgentArchitectureDemo.vue | 2 +- .../appendix/agent-intro/AgentMemoryDemo.vue | 6 +- .../agent-intro/AgentMemoryPrinciple.vue | 10 +- .../agent-intro/AgentMultiToolPrinciple.vue | 12 +- .../agent-intro/AgentPlanningDemo.vue | 8 +- .../agent-intro/AgentQuickStartDemo.vue | 12 +- .../agent-intro/AgentTaskFlowDemo.vue | 2 +- .../appendix/agent-intro/AgentToolUseDemo.vue | 6 +- .../agent-intro/AgentWorkflowDemo.vue | 2 +- .../ai-history/AttentionMechanismDemo.vue | 2 +- .../ai-history/BackpropagationDemo.vue | 2 +- .../ai-history/CombinatorialExplosionDemo.vue | 4 +- .../DiscriminativeVsGenerativeDemo.vue | 2 +- .../appendix/ai-history/GPTEvolutionDemo.vue | 2 +- .../NeuralNetworkVisualizationDemo.vue | 2 +- .../ai-history/RuleBasedVsLearningDemo.vue | 2 +- .../appendix/api-design/DocumentationDemo.vue | 4 +- .../appendix/api-design/ErrorHandlingDemo.vue | 4 +- .../appendix/api-design/HttpMethodsDemo.vue | 6 +- .../api-design/RequestStructureDemo.vue | 4 +- .../appendix/api-design/ResourceAnalogy.vue | 4 +- .../api-design/ResponseStructureDemo.vue | 2 +- .../appendix/api-design/RestfulDesignDemo.vue | 10 +- .../appendix/api-design/StatusCodeDemo.vue | 4 +- .../api-design/VersioningStrategyDemo.vue | 4 +- .../appendix/api-intro/ApiConceptDemo.vue | 4 +- .../appendix/api-intro/ApiDocumentDemo.vue | 2 +- .../appendix/api-intro/ApiMethodDemo.vue | 6 +- .../appendix/api-intro/ApiPlayground.vue | 4 +- .../appendix/api-intro/ApiQuickStartDemo.vue | 2 +- .../appendix/api-intro/RealWorldApiDemo.vue | 6 +- .../api-intro/RequestResponseFlow.vue | 4 +- .../appendix/audio-intro/ASRvsTTSDemo.vue | 24 +- .../audio-intro/AudioQuickStartDemo.vue | 14 +- .../audio-intro/AudioTokenizationDemo.vue | 18 +- .../audio-intro/AudioWaveformDemo.vue | 2 +- .../audio-intro/EmotionControlDemo.vue | 18 +- .../audio-intro/MelSpectrogramDemo.vue | 12 +- .../appendix/audio-intro/TTSPipelineDemo.vue | 20 +- .../appendix/audio-intro/VoiceCloningDemo.vue | 22 +- .../appendix/auth-design/AuthBasicsDemo.vue | 10 +- .../auth-design/AuthEvolutionDemo.vue | 14 +- .../auth-design/AuthInteractiveLoginDemo.vue | 12 +- .../appendix/auth-design/AuthNvsAuthZDemo.vue | 10 +- .../appendix/auth-design/CSRFDefenseDemo.vue | 12 +- .../appendix/auth-design/JWTWorkflowDemo.vue | 14 +- .../appendix/auth-design/OAuth2FlowDemo.vue | 10 +- .../auth-design/PasswordHashingDemo.vue | 12 +- .../auth-design/SessionCookieDemo.vue | 12 +- .../appendix/auth-design/SessionVsJWTDemo.vue | 10 +- .../ArchitectureComparisonDemo.vue | 108 ++- .../BackendEvolutionDemo.vue | 6 +- .../BackendQuickStartDemo.vue | 2 +- .../backend-evolution/ContainerDockerDemo.vue | 106 ++- .../backend-evolution/DeploymentFlowDemo.vue | 8 +- .../backend-evolution/EvolutionIntroDemo.vue | 84 ++- .../backend-evolution/KubernetesDemo.vue | 12 +- .../MicroserviceLatencyDemo.vue | 4 +- .../backend-evolution/MicroservicesDemo.vue | 12 +- .../backend-evolution/MonolithDemo.vue | 127 ++-- .../MonolithReleaseRiskDemo.vue | 8 +- .../MonolithVsMicroserviceDemo.vue | 12 +- .../backend-evolution/PhysicalServerDemo.vue | 172 ++--- .../backend-evolution/ScalingStrategyDemo.vue | 6 +- .../ServerlessCostAutoScaleDemo.vue | 2 +- .../backend-evolution/ServerlessDemo.vue | 16 +- .../TechStackTimelineDemo.vue | 104 ++- .../BackendLanguagesDemo.vue | 18 +- .../ConcurrencyModelDemo.vue | 10 +- .../DeveloperEfficiencyDemo.vue | 10 +- .../LanguageComparisonDemo.vue | 10 +- .../LanguageEcosystemDemo.vue | 10 +- .../LanguageSelectorDemo.vue | 14 +- .../MemoryManagementDemo.vue | 12 +- .../PerformanceBenchmarkDemo.vue | 10 +- .../SyntaxComparisonDemo.vue | 12 +- .../CleanArchitectureDemo.vue | 14 +- .../ControllerLayerDemo.vue | 4 +- .../DependencyDirectionDemo.vue | 2 +- .../DtoFlowDemo.vue | 4 +- .../LayeredArchitectureDemo.vue | 2 +- .../RepositoryLayerDemo.vue | 14 +- .../ServiceLayerDemo.vue | 6 +- .../browser-devtools/BrowserDevToolsDemo.vue | 2 +- .../BrowserDevToolsLiveDemo.vue | 4 +- .../browser-devtools/DevToolsConsoleDemo.vue | 2 +- .../browser-devtools/DevToolsElementsDemo.vue | 2 +- .../browser-devtools/DevToolsSourcesDemo.vue | 2 +- .../CompositeDemo.vue | 8 +- .../DomToRenderTreeDemo.vue | 8 +- .../LayoutReflowDemo.vue | 10 +- .../MacroMicroTaskDemo.vue | 10 +- .../PaintLayerDemo.vue | 10 +- .../RenderingPerformanceDemo.vue | 8 +- .../RenderingPipelineDemo.vue | 14 +- .../cache-design/CacheArchitectureDemo.vue | 10 +- .../CacheArchitectureOverview.vue | 8 +- .../cache-design/CacheHierarchyDemo.vue | 22 +- .../cache-design/CacheLifecycleDemo.vue | 10 +- .../CacheMonitoringDashboardDemo.vue | 12 +- .../CachePatternComparisonDemo.vue | 24 +- .../cache-design/CachePatternsDemo.vue | 20 +- .../cache-design/CacheProblemsDemo.vue | 32 +- .../EcommerceCacheArchitectureDemo.vue | 2 +- .../LocalVsDistributedCacheDemo.vue | 14 +- .../cache-design/LocalityPrincipleDemo.vue | 16 +- .../cache-design/MultiLevelCacheDemo.vue | 16 +- .../cache-design/ProductCacheDemo.vue | 32 +- .../canvas-intro/AnimationLoopDemo.vue | 8 +- .../canvas-intro/CanvasBasicsDemo.vue | 4 +- .../canvas-intro/CoordinateSystemDemo.vue | 10 +- .../canvas-intro/EventHandlingDemo.vue | 12 +- .../canvas-intro/ParticleSystemDemo.vue | 6 +- .../appendix/canvas-intro/PerformanceDemo.vue | 8 +- .../cloud-iam/AccessKeyManagementDemo.vue | 462 ++++-------- .../appendix/cloud-iam/BestPracticesDemo.vue | 476 +++---------- .../cloud-iam/CrossAccountAccessDemo.vue | 215 ++---- .../appendix/cloud-iam/IAMStructure.vue | 238 +++---- .../cloud-iam/IamRamComparisonDemo.vue | 397 ++++------- .../cloud-iam/IdentityProviderDemo.vue | 409 +++-------- .../appendix/cloud-iam/MfaSecurityDemo.vue | 281 +++----- .../cloud-iam/PermissionHierarchyDemo.vue | 359 +++------- .../appendix/cloud-iam/PolicyEditorDemo.vue | 6 +- .../appendix/cloud-iam/RolePolicyDemo.vue | 518 ++++---------- .../appendix/cloud-services/ApiCallDemo.vue | 6 +- .../cloud-services/CloudHistoryDemo.vue | 8 +- .../cloud-services/CloudServicesMapDemo.vue | 2 +- .../cloud-services/CloudServicesOverview.vue | 6 +- .../cloud-services/ComputeInstanceDemo.vue | 6 +- .../cloud-services/ComputeServicesDemo.vue | 2 +- .../cloud-services/DeployWorkflowDemo.vue | 8 +- .../cloud-services/K8sServicesDemo.vue | 2 +- .../cloud-services/NetworkServicesDemo.vue | 6 +- .../cloud-services/PricingCalculator.vue | 6 +- .../cloud-services/ProviderComparison.vue | 6 +- .../cloud-services/RegionLatencyDemo.vue | 8 +- .../cloud-services/SecurityServicesDemo.vue | 4 +- .../cloud-services/StorageServicesDemo.vue | 4 +- .../cloud-services/StorageTypeDemo.vue | 6 +- .../cloud-storage-cdn/AccessAnalyticsDemo.vue | 8 +- .../cloud-storage-cdn/CachePolicyDemo.vue | 2 +- .../cloud-storage-cdn/CdnAccelerationDemo.vue | 216 +++--- .../EdgeNodeDistributionDemo.vue | 2 +- .../HttpsOptimizationDemo.vue | 8 +- .../cloud-storage-cdn/ObjectStorageDemo.vue | 152 ++-- .../TrafficSchedulingDemo.vue | 8 +- .../cloud-storage-cdn/UploadProcessDemo.vue | 4 +- .../cloud-topology/AvailabilityZoneDemo.vue | 8 +- .../cloud-topology/ComputeTopologyDemo.vue | 18 +- .../cloud-topology/DisasterRecoveryDemo.vue | 10 +- .../cloud-topology/NetworkFlowDemo.vue | 12 +- .../cloud-topology/ResourceTopologyDemo.vue | 10 +- .../cloud-topology/StorageTopologyDemo.vue | 10 +- .../cloud-topology/SubnetDesignDemo.vue | 12 +- .../cloud-topology/VpcArchitectureDemo.vue | 6 +- .../ComponentHierarchyDemo.vue | 16 +- .../EventBusDemo.vue | 18 +- .../MobxReactivityDemo.vue | 14 +- .../PropsFlowDemo.vue | 10 +- .../ReduxFlowDemo.vue | 20 +- .../StateManagementComparisonDemo.vue | 10 +- .../VuexPiniaDemo.vue | 18 +- .../ZustandJotaiDemo.vue | 22 +- .../concurrency-models/AsyncAwaitDemo.vue | 8 +- .../ConcurrentVsParallelDemo.vue | 12 +- .../CoroutineLightweightDemo.vue | 4 +- .../concurrency-models/EventLoopDemo.vue | 4 +- .../GoroutineGreenThreadDemo.vue | 10 +- .../ProcessIsolationDemo.vue | 4 +- .../ProcessThreadCoroutineDemo.vue | 6 +- .../ThreadSchedulingDemo.vue | 4 +- .../context-engineering/AgentContextFlow.vue | 4 +- .../ContextCompressionDemo.vue | 4 +- .../ContextWindowVisualizer.vue | 12 +- .../IntroProblemReasonSolution.vue | 2 +- .../context-engineering/KVCacheDemo.vue | 10 +- .../context-engineering/LostInMiddleDemo.vue | 8 +- .../MemoryPalaceActionDemo.vue | 8 +- .../context-engineering/MemoryPalaceDemo.vue | 10 +- .../context-engineering/RAGSimulationDemo.vue | 6 +- .../SelectiveContextDemo.vue | 8 +- .../context-engineering/SlidingWindowDemo.vue | 8 +- .../appendix/database-intro/BPlusTreeDemo.vue | 8 +- .../database-intro/DatabaseEvolutionDemo.vue | 14 +- .../database-intro/DatabaseIndexDemo.vue | 8 +- .../database-intro/DatabaseRelationDemo.vue | 10 +- .../database-intro/QueryOptimizationDemo.vue | 6 +- .../database-intro/RelationalDataDemo.vue | 6 +- .../database-intro/SqlPlaygroundDemo.vue | 6 +- .../database-intro/TransactionACIDDemo.vue | 12 +- .../deployment/DeploymentBuildDemo.vue | 6 +- .../deployment/DeploymentCicdDemo.vue | 6 +- .../appendix/deployment/DeploymentDnsDemo.vue | 6 +- .../deployment/DeploymentHttpsDemo.vue | 4 +- .../deployment/DeploymentMonitorDemo.vue | 4 +- .../deployment/DeploymentOverviewDemo.vue | 10 +- .../deployment/DeploymentServerDemo.vue | 4 +- .../AssetFingerprintDemo.vue | 18 +- .../BuildPipelineDemo.vue | 14 +- .../BundlerComparisonDemo.vue | 18 +- .../CodeSplittingDemo.vue | 14 +- .../DependencyGraphDemo.vue | 6 +- .../frontend-engineering/HotReloadDemo.vue | 14 +- .../frontend-engineering/SourceMapDemo.vue | 8 +- .../frontend-engineering/TreeShakingDemo.vue | 10 +- .../FrontendEvolutionDemo.vue | 94 ++- .../ImperativeVsDeclarativeDemo.vue | 12 +- .../frontend-evolution/JQueryVsStateDemo.vue | 18 +- .../RenderingStrategyDemo.vue | 8 +- .../frontend-evolution/ResponsiveGridDemo.vue | 2 +- .../frontend-evolution/RoutingModeDemo.vue | 10 +- .../frontend-evolution/SliceRequestDemo.vue | 20 +- .../CachingStrategyDemo.vue | 14 +- .../CriticalRenderingPathDemo.vue | 16 +- .../ImageOptimizationDemo.vue | 4 +- .../frontend-performance/LazyLoadingDemo.vue | 18 +- .../PerformanceMetricsDemo.vue | 8 +- .../PerformanceOverviewDemo.vue | 6 +- .../ReflowRepaintDemo.vue | 10 +- .../VirtualScrollingDemo.vue | 8 +- .../frontend-routing/DynamicRoutesDemo.vue | 16 +- .../frontend-routing/HashVsHistoryDemo.vue | 12 +- .../frontend-routing/MpaRoutingDemo.vue | 12 +- .../frontend-routing/NestedRoutesDemo.vue | 18 +- .../frontend-routing/RouteGuardsDemo.vue | 20 +- .../frontend-routing/RouteMatchingDemo.vue | 16 +- .../RouterArchitectureDemo.vue | 14 +- .../frontend-routing/RoutingModesDemo.vue | 16 +- .../frontend-routing/SpaNavigationDemo.vue | 16 +- .../appendix/gateway-proxy/ApiGatewayDemo.vue | 6 +- .../gateway-proxy/AuthMiddlewareDemo.vue | 10 +- .../gateway-proxy/LoadBalancingDemo.vue | 14 +- .../gateway-proxy/NginxArchitectureDemo.vue | 8 +- .../gateway-proxy/RateLimitingDemo.vue | 30 +- .../gateway-proxy/ReverseProxyDemo.vue | 2 +- .../gateway-proxy/RoutingRulesDemo.vue | 8 +- .../gateway-proxy/SslTerminationDemo.vue | 14 +- .../appendix/git-intro/GitBranchMergeDemo.vue | 12 +- .../appendix/git-intro/GitCommandDemo.vue | 10 +- .../appendix/git-intro/GitConflictDemo.vue | 10 +- .../appendix/git-intro/GitRemoteDemo.vue | 12 +- .../appendix/git-intro/GitScenariosDemo.vue | 12 +- .../appendix/git-intro/GitStashDemo.vue | 12 +- .../appendix/git-intro/GitStorageDemo.vue | 6 +- .../appendix/git-intro/GitThreeAreasDemo.vue | 18 +- .../appendix/git-intro/GitWorkflowDemo.vue | 8 +- .../appendix/ide-intro/AiHelpDemo.vue | 6 +- .../ide-intro/IdeArchitectureDemo.vue | 8 +- .../appendix/ide-intro/VirtualVSCodeDemo.vue | 8 +- .../appendix/image-gen-intro/CFGScaleDemo.vue | 16 +- .../image-gen-intro/ControlNetDemo.vue | 18 +- .../image-gen-intro/DiffusionProcessDemo.vue | 4 +- .../image-gen-intro/FlowMatchingDemo.vue | 2 +- .../ImageGenQuickStartDemo.vue | 2 +- .../image-gen-intro/LatentSpaceViz.vue | 2 +- .../appendix/image-gen-intro/LoRADemo.vue | 20 +- .../image-gen-intro/PromptEngineeringDemo.vue | 6 +- .../image-gen-intro/PromptVisualizer.vue | 2 +- .../image-gen-intro/SamplerComparisonDemo.vue | 12 +- .../image-gen-intro/UNetDenoiseDemo.vue | 12 +- .../image-gen-intro/VaeEncoderDemo.vue | 6 +- .../appendix/llm-intro/EmbeddingDemo.vue | 8 +- .../llm-intro/LinearAttentionDemo.vue | 4 +- .../appendix/llm-intro/LlmQuickStartDemo.vue | 2 +- .../components/appendix/llm-intro/MoEDemo.vue | 8 +- .../llm-intro/NextTokenPrediction.vue | 6 +- .../appendix/llm-intro/RNNvsTransformer.vue | 8 +- .../appendix/llm-intro/ThinkingModelDemo.vue | 4 +- .../appendix/llm-intro/TokenizationDemo.vue | 6 +- .../appendix/llm-intro/TokenizerToMatrix.vue | 6 +- .../llm-intro/TrainingInferenceDemo.vue | 26 +- .../load-balancing/AutoScalingDemo.vue | 10 +- .../BlueGreenDeploymentDemo.vue | 6 +- .../load-balancing/CanaryReleaseDemo.vue | 4 +- .../load-balancing/HealthCheckDemo.vue | 10 +- .../load-balancing/LoadBalancerTypesDemo.vue | 12 +- .../load-balancing/MultiRegionDemo.vue | 8 +- .../load-balancing/SessionPersistenceDemo.vue | 16 +- .../load-balancing/WeightedRoutingDemo.vue | 8 +- .../appendix/operations/AlertFlowDemo.vue | 10 +- .../operations/CapacityPlanningDemo.vue | 8 +- .../operations/IncidentResponseDemo.vue | 12 +- .../operations/MonitoringDashboardDemo.vue | 2 +- .../operations/TraceVisualizationDemo.vue | 14 +- .../prompt-engineering/ChainOfThoughtDemo.vue | 2 +- .../PromptQuickStartDemo.vue | 6 +- .../PromptRobustnessDemo.vue | 6 +- .../prompt-engineering/PromptSecurityDemo.vue | 2 +- .../TrainingProcessDemo.vue | 4 +- .../appendix/queue-design/CouplingDemo.vue | 18 +- .../queue-design/DeadLetterQueueDemo.vue | 20 +- .../appendix/queue-design/DecouplingDemo.vue | 16 +- .../queue-design/DelayedMessageDemo.vue | 22 +- .../appendix/queue-design/IdempotenceDemo.vue | 18 +- .../queue-design/MQArchitectureDemo.vue | 2 +- .../queue-design/MQComparisonDemo.vue | 2 +- .../MessageQueueComparisonDemo.vue | 8 +- .../MessageQueueComponentsDemo.vue | 6 +- .../queue-design/MessageQueueDemo.vue | 6 +- .../appendix/queue-design/PeakShavingDemo.vue | 8 +- .../queue-design/PointToPointVsPubSubDemo.vue | 12 +- .../queue-design/ProducerConsumerDemo.vue | 2 +- .../appendix/queue-design/PubSubDemo.vue | 20 +- .../appendix/queue-design/ReliabilityDemo.vue | 14 +- .../queue-design/SeckillSystemDemo.vue | 30 +- .../terminal-intro/AdvancedTUIDemo.vue | 2 +- .../terminal-intro/ArchitectureDemo.vue | 4 +- .../terminal-intro/BufferSwitchDemo.vue | 4 +- .../appendix/terminal-intro/CellInspector.vue | 2 +- .../appendix/terminal-intro/CookedRawDemo.vue | 4 +- .../terminal-intro/EscapeParserDemo.vue | 2 +- .../terminal-intro/EscapeSequences.vue | 2 +- .../appendix/terminal-intro/FlowDiagram.vue | 2 +- .../terminal-intro/InputVisualizer.vue | 4 +- .../appendix/terminal-intro/SignalsDemo.vue | 4 +- .../terminal-intro/TerminalDefinition.vue | 2 +- .../terminal-intro/TerminalHandsOn.vue | 8 +- .../terminal-intro/TerminalOSDemo.vue | 4 +- .../appendix/terminal-intro/WebTerminal.vue | 8 +- .../tracking-design/DataModelDesignDemo.vue | 14 +- .../tracking-design/DataPipelineDemo.vue | 6 +- .../tracking-design/PrivacyComplianceDemo.vue | 14 +- .../tracking-design/RealWorldCaseDemo.vue | 16 +- .../tracking-design/ToolSelectionDemo.vue | 6 +- .../TrackingMethodsComparisonDemo.vue | 4 +- .../tracking-design/TrackingOverviewDemo.vue | 2 +- .../tracking-design/TrackingTypesDemo.vue | 8 +- .../url-to-browser/BrowserRenderingDemo.vue | 8 +- .../appendix/url-to-browser/DnsLookupDemo.vue | 6 +- .../url-to-browser/HttpExchangeDemo.vue | 6 +- .../url-to-browser/TcpHandshakeDemo.vue | 6 +- .../appendix/url-to-browser/UrlParserDemo.vue | 12 +- .../url-to-browser/UrlToBrowserQuickStart.vue | 4 +- .../appendix/vlm-intro/AttentionDemo.vue | 2 +- .../vlm-intro/FeatureAlignmentDemo.vue | 4 +- .../vlm-intro/LinearProjectionDemo.vue | 2 +- .../ModelArchitectureComparisonDemo.vue | 4 +- .../appendix/vlm-intro/PatchifyDemo.vue | 4 +- .../vlm-intro/PositionalEmbeddingDemo.vue | 2 +- .../appendix/vlm-intro/ProjectorDemo.vue | 4 +- .../vlm-intro/TrainingPipelineDemo.vue | 6 +- .../appendix/vlm-intro/VLMInferenceDemo.vue | 2 +- .../appendix/vlm-intro/ViTOutputDemo.vue | 8 +- .../appendix/vlm-intro/VlmQuickStartDemo.vue | 10 +- .../web-basics/BigFrontendScopeDemo.vue | 10 +- .../web-basics/BrowserRenderingDemo.vue | 12 +- .../web-basics/ComponentReusabilityDemo.vue | 6 +- .../appendix/web-basics/CssBoxModel.vue | 379 ++++------ .../web-basics/CssCommonProperties.vue | 6 +- .../appendix/web-basics/CssFlexbox.vue | 204 +++--- .../appendix/web-basics/CssLayoutDemo.vue | 8 +- .../appendix/web-basics/CssPlaygroundDemo.vue | 6 +- .../appendix/web-basics/CssSelectorsDemo.vue | 2 +- .../web-basics/DeploymentArchitecture.vue | 8 +- .../appendix/web-basics/DnsLookupDemo.vue | 8 +- .../appendix/web-basics/DomManipulator.vue | 220 +++--- .../web-basics/FrontendEvolutionDemo.vue | 4 +- .../appendix/web-basics/HttpExchangeDemo.vue | 8 +- .../ImperativeVsDeclarativeDemo.vue | 12 +- .../appendix/web-basics/JQueryVsStateDemo.vue | 4 +- .../appendix/web-basics/NetworkLayers.vue | 8 +- .../web-basics/NetworkTroubleshooting.vue | 16 +- .../web-basics/ResponsiveGridDemo.vue | 2 +- .../appendix/web-basics/RoutingModeDemo.vue | 4 +- .../appendix/web-basics/SemanticTagsDemo.vue | 4 +- .../web-basics/SpaStatePreservationDemo.vue | 8 +- .../appendix/web-basics/SubnetCalculator.vue | 10 +- .../appendix/web-basics/TcpHandshakeDemo.vue | 6 +- .../appendix/web-basics/TcpUdpComparison.vue | 12 +- .../appendix/web-basics/UrlParserDemo.vue | 8 +- .../appendix/web-basics/UrlToBrowserDemo.vue | 4 +- .../web-basics/VueReactComparisonDemo.vue | 2 +- .../appendix/web-basics/WebTechTriad.vue | 673 +++++------------- 373 files changed, 3441 insertions(+), 5629 deletions(-) diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentArchitectureDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentArchitectureDemo.vue index aa00cfd..4921341 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentArchitectureDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentArchitectureDemo.vue @@ -156,7 +156,7 @@ const current = ref(modules[0]) .icon { width: 28px; height: 28px; - border-radius: 8px; + border-radius: 6px; display: grid; place-items: center; background: var(--vp-c-bg-soft); diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryDemo.vue index 499d374..4d50d8d 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryDemo.vue @@ -261,7 +261,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) padding: 12px; min-height: 120px; max-height: 160px; - overflow-y: auto; + } .msg-row { @@ -421,7 +421,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) gap: 8px; padding: 10px 14px; background: #dcfce7; - border-radius: 8px; + border-radius: 6px; margin-bottom: 16px; font-size: 12px; color: #166534; @@ -433,7 +433,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) gap: 8px; padding: 10px 14px; background: var(--vp-c-brand-soft); - border-radius: 8px; + border-radius: 6px; font-size: 12px; color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryPrinciple.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryPrinciple.vue index a1a158f..52b4477 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryPrinciple.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryPrinciple.vue @@ -588,7 +588,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s /* 对话区 */ .chat-area { background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 12px; margin-bottom: 16px; } @@ -613,7 +613,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s .messages { max-height: 200px; - overflow-y: auto; + display: flex; flex-direction: column; gap: 10px; @@ -732,7 +732,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s .memory-panel { background: var(--vp-c-bg-soft); border: 2px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; cursor: pointer; transition: all 0.3s; @@ -778,7 +778,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s padding: 10px; min-height: 80px; max-height: 120px; - overflow-y: auto; + } .empty { @@ -1060,7 +1060,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s gap: 12px; padding: 12px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; } .practice-icon { diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMultiToolPrinciple.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMultiToolPrinciple.vue index 283dfe8..875714a 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMultiToolPrinciple.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMultiToolPrinciple.vue @@ -435,7 +435,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .phase { margin-bottom: 12px; border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; opacity: 0.5; transition: all 0.3s; @@ -525,7 +525,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st gap: 12px; padding: 12px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; border: 2px solid transparent; transition: all 0.3s; position: relative; @@ -685,7 +685,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .final-output { padding: 12px; background: #dcfce7; - border-radius: 8px; + border-radius: 6px; } .output-bubble { @@ -704,7 +704,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .control-btn { padding: 10px 24px; - border-radius: 8px; + border-radius: 6px; font-size: 14px; cursor: pointer; transition: all 0.2s; @@ -762,7 +762,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .explanation-card { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 14px; text-align: center; } @@ -788,7 +788,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .comparison-section { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 14px; } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentPlanningDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentPlanningDemo.vue index c50cfbd..ef91e13 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentPlanningDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentPlanningDemo.vue @@ -304,7 +304,7 @@ reset() .goal-bar { background: var(--vp-c-brand-soft); border-left: 3px solid var(--vp-c-brand); - border-radius: 8px; + border-radius: 6px; padding: 10px 14px; margin-bottom: 16px; font-size: 14px; @@ -403,7 +403,7 @@ reset() .log-box, .thought-box { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; } @@ -431,7 +431,7 @@ reset() padding: 10px 12px; min-height: 100px; max-height: 140px; - overflow-y: auto; + } .empty { @@ -534,7 +534,7 @@ reset() gap: 8px; padding: 10px 14px; background: var(--vp-c-brand-soft); - border-radius: 8px; + border-radius: 6px; font-size: 12px; color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentQuickStartDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentQuickStartDemo.vue index 1bf2ef5..7d76427 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentQuickStartDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentQuickStartDemo.vue @@ -476,7 +476,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) .thinking-section { margin-bottom: 10px; border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; } @@ -516,7 +516,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) .tools-section { margin-bottom: 10px; border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; } @@ -530,7 +530,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) gap: 10px; padding: 10px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; margin-bottom: 8px; border: 1px solid var(--vp-c-divider); transition: all 0.3s; @@ -603,7 +603,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) padding: 12px; background: #dcfce7; border: 1px solid #86efac; - border-radius: 8px; + border-radius: 6px; } .response-header { @@ -628,7 +628,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) background: var(--vp-c-brand); color: white; border: none; - border-radius: 8px; + border-radius: 6px; font-size: 13px; cursor: pointer; transition: background 0.2s; @@ -651,7 +651,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) margin-top: 16px; padding: 12px 16px; background: var(--vp-c-brand-soft); - border-radius: 8px; + border-radius: 6px; font-size: 13px; } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentTaskFlowDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentTaskFlowDemo.vue index 3f9fcb2..054f46e 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentTaskFlowDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentTaskFlowDemo.vue @@ -163,7 +163,7 @@ const steps = [ .n { width: 26px; height: 26px; - border-radius: 8px; + border-radius: 6px; display: grid; place-items: center; background: var(--vp-c-bg-soft); diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentToolUseDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentToolUseDemo.vue index 1f8f292..79092a4 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentToolUseDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentToolUseDemo.vue @@ -266,7 +266,7 @@ const reset = () => { currentStep.value = 0 } .user-input-bar { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 10px 14px; margin-bottom: 16px; font-size: 14px; @@ -460,7 +460,7 @@ const reset = () => { currentStep.value = 0 } .final-result { background: var(--vp-c-brand-soft); border-left: 3px solid var(--vp-c-brand); - border-radius: 8px; + border-radius: 6px; padding: 12px 14px; margin-bottom: 16px; font-size: 13px; @@ -513,7 +513,7 @@ const reset = () => { currentStep.value = 0 } gap: 8px; padding: 10px 14px; background: var(--vp-c-brand-soft); - border-radius: 8px; + border-radius: 6px; font-size: 12px; color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentWorkflowDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentWorkflowDemo.vue index d818a38..c53fe8e 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentWorkflowDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentWorkflowDemo.vue @@ -179,7 +179,7 @@ const reset = () => { .icon { width: 28px; height: 28px; - border-radius: 8px; + border-radius: 6px; display: grid; place-items: center; background: var(--vp-c-bg-soft); diff --git a/docs/.vitepress/theme/components/appendix/ai-history/AttentionMechanismDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/AttentionMechanismDemo.vue index ab687d4..2dbf367 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/AttentionMechanismDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/AttentionMechanismDemo.vue @@ -140,7 +140,7 @@ const getInsight = (index) => { margin-bottom: 24px; padding: 16px; background-color: var(--vp-c-bg-alt); - border-radius: 8px; + border-radius: 6px; } .word-token { diff --git a/docs/.vitepress/theme/components/appendix/ai-history/BackpropagationDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/BackpropagationDemo.vue index cb2ede9..98e9331 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/BackpropagationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/BackpropagationDemo.vue @@ -234,7 +234,7 @@ onMounted(() => { display: flex; justify-content: center; background-color: var(--vp-c-bg-alt); - border-radius: 8px; + border-radius: 6px; padding: 10px; } diff --git a/docs/.vitepress/theme/components/appendix/ai-history/CombinatorialExplosionDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/CombinatorialExplosionDemo.vue index 714fb26..87a6aa2 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/CombinatorialExplosionDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/CombinatorialExplosionDemo.vue @@ -213,7 +213,7 @@ watch([featureCount, valuesPerFeature], () => { text-align: center; background-color: var(--vp-c-bg-alt); padding: 16px; - border-radius: 8px; + border-radius: 6px; } .formula-suffix { @@ -234,7 +234,7 @@ watch([featureCount, valuesPerFeature], () => { width: 50px; height: 50px; border: 2px solid; - border-radius: 8px; + border-radius: 6px; display: flex; flex-direction: column; align-items: center; diff --git a/docs/.vitepress/theme/components/appendix/ai-history/DiscriminativeVsGenerativeDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/DiscriminativeVsGenerativeDemo.vue index 3d4d34f..ebf6b9c 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/DiscriminativeVsGenerativeDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/DiscriminativeVsGenerativeDemo.vue @@ -208,7 +208,7 @@ const mode = ref('discriminative') gap: 10px; background-color: var(--vp-c-bg); padding: 16px; - border-radius: 8px; + border-radius: 6px; } .io-box { diff --git a/docs/.vitepress/theme/components/appendix/ai-history/GPTEvolutionDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/GPTEvolutionDemo.vue index 080f914..0c65092 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/GPTEvolutionDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/GPTEvolutionDemo.vue @@ -149,7 +149,7 @@ const handleTabClick = (tab) => { } .main-card { - border-radius: 8px; + border-radius: 6px; } .card-header { diff --git a/docs/.vitepress/theme/components/appendix/ai-history/NeuralNetworkVisualizationDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/NeuralNetworkVisualizationDemo.vue index 2c2e9af..6095a26 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/NeuralNetworkVisualizationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/NeuralNetworkVisualizationDemo.vue @@ -334,7 +334,7 @@ const isConnectionFocus = (c) => { display: flex; justify-content: center; background-color: var(--vp-c-bg-alt); - border-radius: 8px; + border-radius: 6px; padding: 10px; } diff --git a/docs/.vitepress/theme/components/appendix/ai-history/RuleBasedVsLearningDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/RuleBasedVsLearningDemo.vue index 8296d1e..7253124 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/RuleBasedVsLearningDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/RuleBasedVsLearningDemo.vue @@ -274,7 +274,7 @@ const train = () => { .result-box { background-color: var(--vp-c-bg-alt); padding: 12px; - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--vp-c-divider); text-align: center; } diff --git a/docs/.vitepress/theme/components/appendix/api-design/DocumentationDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/DocumentationDemo.vue index 5d24ab1..bb459eb 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/DocumentationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/DocumentationDemo.vue @@ -300,7 +300,7 @@ const currentTool = computed(() => gap: 8px; padding: 12px 16px; border: 2px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; background: var(--vp-c-bg); cursor: pointer; transition: all 0.2s ease; @@ -330,7 +330,7 @@ const currentTool = computed(() => .tool-detail { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; } diff --git a/docs/.vitepress/theme/components/appendix/api-design/ErrorHandlingDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/ErrorHandlingDemo.vue index 5aa4145..320b2e5 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/ErrorHandlingDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/ErrorHandlingDemo.vue @@ -188,7 +188,7 @@ const errorCodeItems = [ flex: 1; padding: 12px; border: 2px solid; - border-radius: 8px; + border-radius: 6px; font-size: 14px; font-weight: 600; cursor: pointer; @@ -227,7 +227,7 @@ const errorCodeItems = [ .comparison { background: var(--vp-c-bg); - border-radius: 8px; + border-radius: 6px; overflow: hidden; } diff --git a/docs/.vitepress/theme/components/appendix/api-design/HttpMethodsDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/HttpMethodsDemo.vue index 895009a..b3490d2 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/HttpMethodsDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/HttpMethodsDemo.vue @@ -268,7 +268,7 @@ const currentMethod = computed(() => .method-detail { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 20px; } @@ -306,7 +306,7 @@ const currentMethod = computed(() => align-items: center; padding: 12px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--vp-c-divider); opacity: 0.6; transition: all 0.2s ease; @@ -361,7 +361,7 @@ const currentMethod = computed(() => .example-item { background: var(--vp-c-bg-soft); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 12px; margin-bottom: 12px; } diff --git a/docs/.vitepress/theme/components/appendix/api-design/RequestStructureDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/RequestStructureDemo.vue index b934ffd..6bd4578 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/RequestStructureDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/RequestStructureDemo.vue @@ -48,7 +48,7 @@ diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/BestPracticesDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/BestPracticesDemo.vue index 2a3ec27..3c79702 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/BestPracticesDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/BestPracticesDemo.vue @@ -3,50 +3,26 @@
权限管理最佳实践 - 理解云账号安全管理的核心原则 + 按优先级实施安全措施
-
-
-
-
-
- {{ practice.icon }} -
-
-
{{ practice.title }}
- {{ practice.priorityText }} -
-
{{ expandedCard === index ? '−' : '+' }}
-
- -
-

{{ practice.description }}

- -
-
✓ 检查清单
-
    -
  • {{ item }}
  • -
-
- -
-
代码示例
-
{{ practice.code }}
-
- -
-
推荐工具
-
- {{ tool }} -
-
+
+
+
+ {{ practice.icon }} + {{ practice.title }} + {{ practice.priorityText }} +
+
+

{{ practice.description }}

+
+ ✓ {{ item }}
@@ -54,7 +30,7 @@
💡 - 核心思想:按照优先级从 P0 开始逐步实施最佳实践。每个改进都能显著提升账号安全性,不要试图一次性完成所有改进。 + 核心思想:按照优先级从 P0 开始逐步实施。每个改进都能显著提升账号安全性。
@@ -69,187 +45,41 @@ const bestPractices = [ icon: '👑', title: '根账号保护', priority: 'p0', - priorityText: 'P0 - 最高优先级', - color: 'rgba(var(--vp-c-brand-delta-rgb), 0.15)', - description: '根账号是云服务的所有者,拥有所有权限。必须实施最高级别的保护措施。', - checklist: [ - '启用 MFA(推荐硬件 MFA 设备)', - '创建 IAM 管理员用户用于日常操作', - '删除或锁定根账号的访问密钥', - '配置根账号使用告警', - '设置账号恢复联系信息' - ], - code: `# AWS CLI - 创建管理员用户并禁用根账号 AK -aws iam create-user --user-name AdminUser -aws iam attach-user-policy --user-name AdminUser \ - --policy-arn arn:aws:iam::aws:policy/AdministratorAccess - -# 删除根账号访问密钥(必须使用根账号登录控制台操作)`, - tools: ['硬件 MFA (YubiKey)', '虚拟 MFA (Google Authenticator)', 'AWS IAM', '阿里云 RAM'] + priorityText: 'P0', + description: '根账号是云服务的所有者,必须实施最高级别的保护。', + checklist: ['启用 MFA', '创建 IAM 管理员用户', '删除根账号访问密钥'] }, { icon: '👤', title: '用户权限最小化', priority: 'p0', - priorityText: 'P0 - 最高优先级', - color: 'rgba(var(--vp-c-brand-rgb), 0.1)', + priorityText: 'P0', description: '遵循最小权限原则,只授予用户完成工作所需的最低权限。', - checklist: [ - '避免使用 AdministratorAccess 等全权限策略', - '使用 IAM 用户组批量管理权限', - '定期审查和删除未使用的 IAM 用户', - '为不同角色创建细粒度的自定义策略', - '使用 IAM Access Analyzer 识别过度宽松的权限' - ], - code: `{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:GetObject", - "s3:PutObject", - "s3:ListBucket" - ], - "Resource": [ - "arn:aws:s3:::my-bucket", - "arn:aws:s3:::my-bucket/*" - ], - "Condition": { - "StringEquals": { - "aws:RequestedRegion": "ap-northeast-1" - } - } - } - ] -}`, - tools: ['IAM Policy Simulator', 'IAM Access Analyzer', 'AWS CloudTrail', 'AWS Config'] + checklist: ['避免全权限策略', '使用用户组管理', '定期审查用户'] }, { icon: '🎭', title: '优先使用 IAM 角色', priority: 'p1', - priorityText: 'P1 - 高优先级', - color: 'var(--vp-c-brand-soft)', - description: 'IAM 角色没有长期凭证,通过临时凭证访问,大大降低凭证泄露风险。', - checklist: [ - 'EC2 实例使用实例角色(Instance Profile)', - 'Lambda 函数使用执行角色', - 'ECS 任务使用任务角色', - '跨账号访问使用角色扮演(AssumeRole)', - 'CI/CD 流水线使用 OIDC 联邦身份' - ], - code: `import boto3 - -# EC2 实例自动使用附加的实例角色 -# 无需提供任何凭证 -s3 = boto3.client('s3') - -# 跨账号角色扮演 -sts = boto3.client('sts') -assumed_role = sts.assume_role( - RoleArn='arn:aws:iam::123456789012:role/CrossAccountRole', - RoleSessionName='MyApplication', - DurationSeconds=3600 -) - -# 使用临时凭证 -temp_creds = assumed_role['Credentials'] -s3_cross = boto3.client( - 's3', - aws_access_key_id=temp_creds['AccessKeyId'], - aws_secret_access_key=temp_creds['SecretAccessKey'], - aws_session_token=temp_creds['SessionToken'] -)`, - tools: ['IAM Roles', 'AWS STS', 'EC2 Instance Profiles', 'Lambda Execution Roles'] + priorityText: 'P1', + description: 'IAM 角色没有长期凭证,通过临时凭证访问,降低泄露风险。', + checklist: ['EC2 使用实例角色', 'Lambda 使用执行角色', '跨账号用 AssumeRole'] }, { icon: '🔑', title: '访问密钥安全管理', priority: 'p1', - priorityText: 'P1 - 高优先级', - color: 'rgba(var(--vp-c-brand-rgb), 0.1)', - description: '如果必须使用访问密钥(AK/SK),需要实施严格的安全管理措施。', - checklist: [ - '绝不将 AK/SK 硬编码在代码或配置文件中', - '使用环境变量或密钥管理服务(如 AWS Secrets Manager)', - '每 90 天轮换一次访问密钥', - '定期审查和删除未使用的访问密钥', - '启用 CloudTrail 记录所有 AK/SK 的使用情况' - ], - code: `# ❌ 错误做法 - 硬编码凭证 -import boto3 - -s3 = boto3.client( - 's3', - aws_access_key_id='AKIAIOSFODNN7EXAMPLE', - aws_secret_access_key='wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY' -) - -# ✅ 正确做法 - 使用环境变量 -import boto3 -import os - -s3 = boto3.client( - 's3', - aws_access_key_id=os.environ.get('AWS_ACCESS_KEY_ID'), - aws_secret_access_key=os.environ.get('AWS_SECRET_ACCESS_KEY') -) - -# ✅ 正确做法 - 使用 AWS Secrets Manager -import boto3 -import json - -secrets_client = boto3.client('secretsmanager') -secret_value = secrets_client.get_secret_value(SecretId='my-app/credentials') -credentials = json.loads(secret_value['SecretString']) - -s3 = boto3.client( - 's3', - aws_access_key_id=credentials['access_key_id'], - aws_secret_access_key=credentials['secret_access_key'] -)`, - tools: ['AWS Secrets Manager', 'HashiCorp Vault', 'Azure Key Vault', 'GCP Secret Manager'] + priorityText: 'P1', + description: '如果必须使用 AK/SK,需要实施严格的安全管理措施。', + checklist: ['不硬编码凭证', '使用密钥管理服务', '定期轮换密钥'] }, { icon: '📊', title: '监控与审计', priority: 'p2', - priorityText: 'P2 - 中优先级', - color: 'var(--vp-c-bg-alt)', - description: '建立全面的监控和审计机制,及时发现和响应安全事件。', - checklist: [ - '启用 CloudTrail 记录所有 API 调用', - '配置关键操作的实时告警(根账号使用、策略变更等)', - '使用 IAM Access Analyzer 持续分析权限', - '定期审查 IAM 用户和权限配置', - '将日志存储到独立的审计账号,防止篡改' - ], - code: `# AWS CloudTrail 配置示例 -aws cloudtrail create-trail \ - --name OrganizationTrail \ - --s3-bucket-name my-cloudtrail-bucket \ - --is-organization-trail \ - --enable-log-file-validation \ - --is-multi-region-trail - -# CloudWatch 告警配置 - 根账号使用 -aws cloudwatch put-metric-alarm \ - --alarm-name RootAccountUsageAlarm \ - --alarm-description "Alert when root account is used" \ - --metric-name RootAccountUsage \ - --namespace CloudTrailMetrics \ - --statistic Sum \ - --period 300 \ - --evaluation-periods 1 \ - --threshold 1 \ - --comparison-operator GreaterThanOrEqualToThreshold - -# IAM Access Analyzer 创建分析器 -aws accessanalyzer create-analyzer \ - --analyzer-name MyOrgAnalyzer \ - --type ORGANIZATION`, - tools: ['AWS CloudTrail', 'AWS CloudWatch', 'IAM Access Analyzer', 'AWS Config', 'AWS Security Hub'] + priorityText: 'P2', + description: '建立全面的监控和审计机制,及时发现安全事件。', + checklist: ['启用 CloudTrail', '配置关键操作告警', '定期审查权限'] } ] @@ -262,236 +92,102 @@ function toggleCard(index) { .best-practices-demo { border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 8px; - padding: 1.5rem; - margin: 1rem 0; - max-height: 600px; - overflow-y: auto; + border-radius: 6px; + padding: 0.75rem; + margin: 0.5rem 0; } .demo-header { - margin-bottom: 1rem; + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.75rem; } -.demo-header h4 { - margin: 0 0 0.5rem 0; - font-weight: 800; - color: var(--vp-c-text-1); +.demo-header .icon { font-size: 1.25rem; } +.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; } + +.practices-list { + display: flex; + flex-direction: column; + gap: 0.4rem; + margin-bottom: 0.75rem; } -.intro-text { - margin: 0; - color: var(--vp-c-text-2); - font-size: 0.9rem; -} - -.demo-content { - margin-bottom: 1rem; -} - -.practices-grid { - display: grid; - gap: 1rem; -} - -.practice-card { +.practice-item { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; - padding: 1.25rem; + border-radius: 6px; cursor: pointer; - transition: all 0.2s ease; + transition: all 0.2s; } -.practice-card:hover { - border-color: var(--vp-c-brand); - transform: translateY(-2px); -} - -.practice-card.expanded { +.practice-item:hover { border-color: var(--vp-c-brand); } +.practice-item.active { border-color: var(--vp-c-brand); background: var(--vp-c-bg-alt); } -.card-header { +.item-header { display: flex; align-items: center; - gap: 1rem; + gap: 0.5rem; + padding: 0.6rem; } -.icon-wrapper { - width: 48px; - height: 48px; - border-radius: 8px; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.5rem; - flex-shrink: 0; -} +.item-icon { font-size: 1rem; } +.item-title { font-weight: 600; font-size: 0.85rem; flex: 1; } -.title-wrapper { - flex: 1; -} - -.title-wrapper h5 { - margin: 0 0 0.25rem 0; - font-size: 1.1rem; +.item-priority { + font-size: 0.65rem; font-weight: 700; - color: var(--vp-c-text-1); + padding: 0.15rem 0.4rem; + border-radius: 3px; } -.priority { - padding: 0.125rem 0.5rem; - border-radius: 4px; - font-size: 0.7rem; - font-weight: 600; - text-transform: uppercase; -} +.item-priority.p0 { background: var(--vp-c-danger); color: #fff; } +.item-priority.p1 { background: var(--vp-c-warning); color: #fff; } +.item-priority.p2 { background: var(--vp-c-brand-soft); color: var(--vp-c-brand-1); } -.priority.p0 { - background: rgba(var(--vp-c-brand-delta-rgb), 0.15); - color: var(--vp-c-brand-delta); -} - -.priority.p1 { - background: rgba(var(--vp-c-brand-rgb), 0.1); - color: var(--vp-c-brand); -} - -.priority.p2 { - background: var(--vp-c-brand-soft); - color: var(--vp-c-brand-1); -} - -.expand-icon { - font-size: 1.5rem; - font-weight: 300; - color: var(--vp-c-text-3); -} - -.card-body { - margin-top: 1.25rem; - padding-top: 1.25rem; +.item-body { + padding: 0 0.6rem 0.6rem; border-top: 1px solid var(--vp-c-divider); + margin-top: 0; + padding-top: 0.5rem; } -.description { - font-size: 0.95rem; - line-height: 1.6; - margin-bottom: 1rem; - color: var(--vp-c-text-2); -} - -.checklist { - margin-bottom: 1.25rem; -} - -.checklist h6 { - margin: 0 0 0.75rem 0; - font-size: 0.9rem; - font-weight: 700; - color: var(--vp-c-brand-1); -} - -.checklist ul { - list-style: none; - padding: 0; - margin: 0; -} - -.checklist li { - padding: 0.375rem 0; - padding-left: 1.5rem; - position: relative; - font-size: 0.9rem; - color: var(--vp-c-text-2); -} - -.checklist li:before { - content: '☐'; - position: absolute; - left: 0; - color: var(--vp-c-brand); -} - -.code-example { - margin-bottom: 1.25rem; -} - -.code-example h6 { - margin: 0 0 0.75rem 0; - font-size: 0.9rem; - font-weight: 700; - color: var(--vp-c-brand-1); -} - -.code-example pre { - background: var(--vp-c-bg); - border: 1px solid var(--vp-c-divider); - border-radius: 6px; - padding: 0.75rem; - overflow-x: auto; - margin: 0; -} - -.code-example code { - color: var(--vp-c-text-2); - font-family: var(--vp-font-family-mono); +.item-desc { font-size: 0.8rem; - line-height: 1.5; + color: var(--vp-c-text-2); + margin: 0 0 0.5rem; + line-height: 1.4; } -.tools h6 { - margin: 0 0 0.75rem 0; - font-size: 0.9rem; - font-weight: 700; - color: var(--vp-c-brand-1); -} - -.tool-tags { +.item-checks { display: flex; flex-wrap: wrap; - gap: 0.5rem; + gap: 0.3rem; } -.tool-tag { - padding: 0.25rem 0.75rem; +.check-tag { + font-size: 0.7rem; + padding: 0.15rem 0.4rem; background: var(--vp-c-brand-soft); color: var(--vp-c-brand-1); - border-radius: 4px; - font-size: 0.8rem; - font-weight: 500; + border-radius: 3px; } .info-box { - padding: 0.75rem; background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - border-left: 4px solid var(--vp-c-brand); + padding: 0.6rem; border-radius: 6px; - font-size: 0.9rem; - line-height: 1.6; + font-size: 0.85rem; color: var(--vp-c-text-2); + display: flex; + gap: 0.25rem; } -.info-box strong { - color: var(--vp-c-text-1); -} - -@media (max-width: 768px) { - .card-header { - flex-wrap: wrap; - } - - .icon-wrapper { - width: 40px; - height: 40px; - font-size: 1.2rem; - } - - .title-wrapper h5 { - font-size: 1rem; - } -} +.info-box .icon { flex-shrink: 0; } +.info-box strong { color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/CrossAccountAccessDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/CrossAccountAccessDemo.vue index d6f1921..df8eead 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/CrossAccountAccessDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/CrossAccountAccessDemo.vue @@ -3,230 +3,173 @@
🔗 跨账号访问 - 理解跨账号访问的 AssumeRole 机制 + AssumeRole 机制
-
-
- - -
- - - -
- - +
+ + + + + +
-
-
Python 代码示例
-
import boto3
-
-# 在账号 A 中使用 IAM 用户凭证
-sts_client = boto3.client('sts')
-
-# 扮演账号 B 的角色
-assumed_role = sts_client.assume_role(
+    
+
Python 示例
+
sts = boto3.client('sts')
+assumed = sts.assume_role(
     RoleArn='arn:aws:iam::123456789012:role/CrossAccountRole',
-    RoleSessionName='MySession',
-    DurationSeconds=3600
+    RoleSessionName='MySession'
 )
-
-# 获取临时凭证
-credentials = assumed_role['Credentials']
-
-# 使用临时凭证访问账号 B 的资源
-s3_client = boto3.client(
-    's3',
-    aws_access_key_id=credentials['AccessKeyId'],
-    aws_secret_access_key=credentials['SecretAccessKey'],
-    aws_session_token=credentials['SessionToken']
-)
-
+# 使用临时凭证访问目标账号资源
💡 - 核心思想:通过角色扮演实现跨账号访问,无需在每个账号创建 IAM 用户,临时凭证自动过期,更安全更易管理。 + 核心思想:通过角色扮演实现跨账号访问,临时凭证自动过期,更安全更易管理。
diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/IAMStructure.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/IAMStructure.vue index cd62928..2423984 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/IAMStructure.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/IAMStructure.vue @@ -6,43 +6,37 @@ 云上权限管理的基础构件
-
-
-
-
{{ layer.icon }}
-
-
{{ layer.name }}
-
{{ layer.shortDesc }}
+
+
+
+ {{ layer.icon }} + {{ layer.name }} + {{ layer.shortDesc }}
-
-
-
- {{ selectedLayerData.icon }} - {{ selectedLayerData.name }} -
-
{{ selectedLayerData.description }}
-
-
示例:
-
    -
  • - {{ example }} -
  • -
-
+
+
+ {{ selectedLayerData.icon }} + {{ selectedLayerData.name }} +
+
{{ selectedLayerData.description }}
+
+ 示例: + {{ example }} +
+
-
- 💡 - 核心思想:IAM 就像公司的门禁系统——根账号是老板(拥有所有钥匙),用户是员工(有特定权限),角色是临时访客证(有时效),策略是"谁能进哪些门"的规则。 -
+
+ 💡 + 核心思想:IAM 就像公司的门禁系统——根账号是老板,用户是员工,角色是临时访客证,策略是"谁能进哪些门"的规则。
@@ -57,61 +51,36 @@ const layers = [ icon: '👑', name: '根账号', shortDesc: '最高权限', - description: '云账号的所有者,拥有全部资源的完全控制权限。建议仅用于初始设置,日常操作使用子账号。', - examples: [ - '创建/删除 IAM 用户', - '管理账单和支付方式', - '关闭账号', - '恢复已删除资源' - ] + description: '云账号的所有者,拥有全部资源的完全控制权限。建议仅用于初始设置。', + examples: ['创建/删除 IAM 用户', '管理账单和支付方式'] }, { icon: '👤', name: 'IAM 用户', shortDesc: '个人身份', - description: '为具体人员(如员工)创建的长期凭证,用于日常登录和操作云服务。', - examples: [ - '开发人员账号', - '运维人员账号', - '只读审计账号', - 'API 调用账号' - ] + description: '为具体人员创建的长期凭证,用于日常登录和操作云服务。', + examples: ['开发人员账号', '运维人员账号'] }, { icon: '👥', name: '用户组', shortDesc: '批量管理', description: '将多个用户归为一组,统一分配权限,简化管理。', - examples: [ - '开发组(开发权限)', - '运维组(运维权限)', - '财务组(账单权限)', - '审计组(只读权限)' - ] + examples: ['开发组', '运维组'] }, { icon: '🎭', name: '角色', shortDesc: '临时授权', description: '一种临时身份,可以被切换或赋予其他账号/服务,具有时效性更安全。', - examples: [ - '跨账号访问角色', - '服务角色(如 Lambda)', - '临时运维角色', - '第三方登录角色' - ] + examples: ['跨账号访问角色', '服务角色'] }, { icon: '📋', name: '策略', shortDesc: '权限规则', description: '定义"谁可以对什么资源执行什么操作"的规则文档,以 JSON 格式编写。', - examples: [ - '允许访问 S3 存储桶', - '禁止删除 EC2 实例', - '只允许查看 RDS', - '允许特定时间段访问' - ] + examples: ['允许访问 S3', '禁止删除 EC2'] } ] @@ -125,53 +94,45 @@ function selectLayer(index) { diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/IamRamComparisonDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/IamRamComparisonDemo.vue index 368e244..f346765 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/IamRamComparisonDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/IamRamComparisonDemo.vue @@ -3,86 +3,59 @@
🔐 IAM vs RAM 对比 - 理解不同云厂商的权限管理服务 + 不同云厂商权限管理服务
-
-
- -
-
- -
IAM
- Identity and Access Management -
+
+
+
AWS IAM
+
+ {{ feature.icon }} + {{ feature.name }} +
+
-
-
-
{{ feature.icon }}
-
- {{ feature.name }} - {{ feature.desc }} -
+
+
+
{{ selectedFeatureData.name }}
+
+
+
AWS IAM
+
{{ selectedFeatureData.awsDetail }}
+
+
VS
+
+
阿里云 RAM
+
{{ selectedFeatureData.ramDetail }}
+
- -
-
-
{{ selectedFeatureData.name }}
-
-
- AWS IAM -

{{ selectedFeatureData.awsDetail }}

- {{ selectedFeatureData.awsExample }} -
-
VS
-
- 阿里云 RAM -

{{ selectedFeatureData.ramDetail }}

- {{ selectedFeatureData.ramExample }} -
-
-
-
- - -
-
- -
RAM
- Resource Access Management -
- -
-
-
{{ feature.icon }}
-
- {{ feature.name }} - {{ feature.desc }} -
-
-
+
+
阿里云 RAM
+
+ {{ feature.icon }} + {{ feature.name }}
💡 - 核心思想:IAM 和 RAM 的核心概念基本一致,只是术语和实现细节略有不同。掌握一个平台后,可以快速迁移到另一个平台。 + 核心思想:IAM 和 RAM 核心概念基本一致,只是术语和实现细节略有不同。
@@ -90,85 +63,36 @@ diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/IdentityProviderDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/IdentityProviderDemo.vue index ec12079..0740bfe 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/IdentityProviderDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/IdentityProviderDemo.vue @@ -3,44 +3,35 @@
🔐 身份提供商集成 - 理解企业 SSO 单点登录流程 + 企业 SSO 单点登录流程
-
-
-
-
{{ index + 1 }}
-
- {{ step.title }} - {{ step.desc }} -
-
-
+
+
+ {{ index + 1 }} + {{ step.title }}
+
-
-
{{ currentStepData.title }}
-

{{ currentStepData.detail }}

- -
-
{{ currentStepData.code }}
-
- -
-
- {{ row.from.name }} - {{ row.action }} - {{ row.to.name }} -
-
+
+
{{ currentStepData.title }}
+

{{ currentStepData.detail }}

+
+ {{ currentStepData.flow[0].from.name }} + {{ currentStepData.flow[0].action }} + {{ currentStepData.flow[0].to.name }}
💡 - 核心思想:通过企业 IdP 统一管理用户身份,避免在每个云平台单独创建账号,提高安全性和管理效率。 + 核心思想:通过企业 IdP 统一管理用户身份,避免在每个云平台单独创建账号。
@@ -51,356 +42,140 @@ import { ref, computed } from 'vue' const currentStep = ref(0) const steps = [ - { title: '用户访问应用', desc: '用户尝试访问企业应用' }, - { title: '重定向到 IdP', desc: '应用将用户重定向到身份提供商' }, - { title: '用户登录认证', desc: '用户在 IdP 输入企业账号密码' }, - { title: '颁发 SAML 令牌', desc: 'IdP 验证成功后颁发 SAML Assertion' }, - { title: '返回应用', desc: '携带令牌返回企业应用' }, - { title: '换取云凭证', desc: '应用使用令牌换取云临时凭证' }, - { title: '访问云资源', desc: '使用临时凭证访问云资源' } + { title: '访问应用' }, + { title: '重定向 IdP' }, + { title: '用户登录' }, + { title: '颁发令牌' }, + { title: '返回应用' }, + { title: '换取凭证' }, + { title: '访问资源' } ] const stepDetails = [ - { - title: '用户访问企业应用', - detail: '用户打开浏览器,访问企业内部的业务系统(如 CRM、ERP 等)。此时用户尚未登录,应用检测到用户没有有效的会话。', - flow: [ - { from: { name: '用户', type: 'user' }, action: '访问 →', to: { name: '企业应用', type: 'app' } } - ] - }, - { - title: '应用重定向到 IdP', - detail: '应用发现用户未登录,生成 SAML Request,将用户浏览器重定向到企业的身份提供商(IdP,如 Azure AD、Okta 等)。', - code: `// SAML Request 示例 - - - https://app.example.com - -`, - flow: [ - { from: { name: '企业应用', type: 'app' }, action: '重定向 →', to: { name: 'IdP', type: 'idp' } } - ] - }, - { - title: '用户在 IdP 登录', - detail: '用户在 IdP 的登录页面输入企业账号和密码。IdP 验证用户身份,可能还需要进行 MFA 多因素认证。', - flow: [ - { from: { name: '用户', type: 'user' }, action: '登录 →', to: { name: 'IdP', type: 'idp' } } - ] - }, - { - title: 'IdP 颁发 SAML Assertion', - detail: '用户认证成功后,IdP 生成包含用户身份和属性的 SAML Assertion(断言),并使用 IdP 的私钥签名。', - code: ` - - - - - user@example.com - - - - - Admin - - - -`, - flow: [ - { from: { name: 'IdP', type: 'idp' }, action: '颁发令牌 →', to: { name: '用户浏览器', type: 'user' } } - ] - }, - { - title: '返回企业应用', - detail: 'IdP 通过浏览器将 SAML Response POST 到企业应用。应用验证 SAML 断言的签名,确认用户身份,建立用户会话。', - flow: [ - { from: { name: '用户浏览器', type: 'user' }, action: 'POST 令牌 →', to: { name: '企业应用', type: 'app' } } - ] - }, - { - title: '换取云临时凭证', - detail: '企业应用使用 SAML Assertion 向云厂商的 STS 服务请求临时安全凭证。云服务验证 SAML 断言后,颁发临时 AK/SK/Token。', - code: `# Python 示例:使用 SAML 换取 AWS 临时凭证 -import boto3 - -# 创建 STS 客户端 -sts = boto3.client('sts') - -# 使用 SAML 断言请求临时凭证 -response = sts.assume_role_with_saml( - RoleArn='arn:aws:iam::123456789012:role/SAML-Role', - PrincipalArn='arn:aws:iam::123456789012:saml-provider/Okta', - SAMLAssertion='VGhpcyBpcyBhIHRlc3QgU0FNTCBhc3NlcnRpb24=', - DurationSeconds=3600 -) - -# 获取临时凭证 -credentials = response['Credentials'] -print(f"Access Key: {credentials['AccessKeyId']}") -print(f"Secret Key: {credentials['SecretAccessKey']}") -print(f"Session Token: {credentials['SessionToken']}")`, - flow: [ - { from: { name: '企业应用', type: 'app' }, action: 'AssumeRole →', to: { name: '云 STS', type: 'cloud' } } - ] - }, - { - title: '访问云资源', - detail: '企业应用使用获取到的临时凭证,调用云服务的 API 访问资源(如 S3、EC2、数据库等)。临时凭证有过期时间,到期后需要重新获取。', - flow: [ - { from: { name: '企业应用', type: 'app' }, action: '访问资源 →', to: { name: '云服务', type: 'cloud' } } - ] - } + { title: '用户访问企业应用', detail: '用户打开浏览器访问企业业务系统,应用检测到用户没有有效会话。', flow: [{ from: { name: '用户' }, action: '访问 →', to: { name: '企业应用' } }] }, + { title: '应用重定向到 IdP', detail: '应用生成 SAML Request,将用户重定向到企业身份提供商。', flow: [{ from: { name: '应用' }, action: '重定向 →', to: { name: 'IdP' } }] }, + { title: '用户在 IdP 登录', detail: '用户在 IdP 登录页面输入企业账号密码,可能需要 MFA 认证。', flow: [{ from: { name: '用户' }, action: '登录 →', to: { name: 'IdP' } }] }, + { title: 'IdP 颁发 SAML 令牌', detail: '用户认证成功后,IdP 生成包含用户身份的 SAML Assertion。', flow: [{ from: { name: 'IdP' }, action: '颁发 →', to: { name: '令牌' } }] }, + { title: '返回企业应用', detail: 'IdP 通过浏览器将 SAML Response POST 到企业应用。', flow: [{ from: { name: '浏览器' }, action: 'POST →', to: { name: '应用' } }] }, + { title: '换取云临时凭证', detail: '应用使用 SAML 向云 STS 服务请求临时安全凭证。', flow: [{ from: { name: '应用' }, action: 'AssumeRole →', to: { name: '云 STS' } }] }, + { title: '访问云资源', detail: '应用使用临时凭证调用云服务 API 访问资源。', flow: [{ from: { name: '应用' }, action: '访问 →', to: { name: '云服务' } }] } ] -const currentStepData = computed(() => { - if (currentStep.value === null) return null - return stepDetails[currentStep.value] -}) - -function goToStep(index) { - currentStep.value = index -} +const currentStepData = computed(() => stepDetails[currentStep.value]) diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/MfaSecurityDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/MfaSecurityDemo.vue index fb6583c..50c118c 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/MfaSecurityDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/MfaSecurityDemo.vue @@ -3,49 +3,47 @@
🔐 多因素认证 - 理解 MFA 双因素认证流程 + MFA 双因素认证流程
-
+
-
🔐
-
密码验证
+ 🔐 + 密码
-
+
-
📱
-
MFA 验证
+ 📱 + MFA
-
+
-
-
登录成功
+ + 成功
-
请输入密码
- +
请输入密码
+
-
MFA 验证
+
MFA 验证码
{{ totpCode }} -
-
-
+
模拟验证码
- +
-
-
🎉
-
登录成功!
-

已通过 MFA 双因素认证

+
+ 🎉 +
登录成功!
+
已通过 MFA 双因素认证
@@ -58,43 +56,27 @@ diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/PermissionHierarchyDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/PermissionHierarchyDemo.vue index 369f6c4..5595d73 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/PermissionHierarchyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/PermissionHierarchyDemo.vue @@ -3,11 +3,11 @@
🏛️ 权限层级结构 - 理解不同权限级别的范围差异 + 不同权限级别的范围差异
-
-
+
+
-
{{ level.icon }}
-
+ {{ level.icon }} +
{{ level.name }} {{ level.scope }}
-
- - {{ perm }} - - - +{{ level.permissions.length - 3 }} - -
-
{{ selectedLevelData.name }} 详情
-
- 权限范围: +
{{ selectedLevelData.name }}
+
+ 范围: {{ selectedLevelData.scope }}
-
- 典型场景: +
+ 场景: {{ selectedLevelData.scenario }}
-
- 拥有权限: -
- - {{ perm.name }} - -
+
+ {{ perm.name }}
💡 - 核心思想:最小权限原则——始终授予用户完成工作所需的最小权限。从低权限开始,根据实际需求逐步提升,而不是一开始就授予高权限。 + 核心思想:最小权限原则——始终授予用户完成工作所需的最小权限。
@@ -76,71 +54,42 @@ const selectedLevel = ref(0) const hierarchyLevels = [ { icon: '👑', - name: '根账号 (Root)', + name: '根账号', scope: '全账号最高权限', - scenario: '账号所有者,拥有云服务的所有权限', - permissions: [ - { name: '完全管理权限', type: 'full' }, - { name: '账单管理', type: 'billing' }, - { name: '组织架构管理', type: 'org' }, - { name: '关闭账号', type: 'critical' }, - { name: '恢复已删除资源', type: 'admin' } - ] + scenario: '账号所有者,拥有所有权限', + permissions: [{ name: '完全管理' }, { name: '账单管理' }, { name: '关闭账号' }] }, { icon: '👤', name: 'IAM 管理员', scope: 'IAM 全权限', scenario: '管理所有 IAM 用户、角色、策略', - permissions: [ - { name: '创建/删除用户', type: 'user' }, - { name: '创建/删除角色', type: 'role' }, - { name: '管理策略', type: 'policy' }, - { name: '查看凭证报告', type: 'audit' } - ] + permissions: [{ name: '创建/删除用户' }, { name: '管理策略' }, { name: '查看凭证' }] }, { icon: '👥', - name: '普通 IAM 用户', + name: '普通用户', scope: '受限权限', - scenario: '日常开发人员,只能访问特定资源', - permissions: [ - { name: '只读访问 EC2', type: 'read' }, - { name: '读写指定 S3 桶', type: 'limited' }, - { name: '查看 CloudWatch 日志', type: 'read' }, - { name: '无法创建 IAM 资源', type: 'deny' } - ] + scenario: '日常开发,只能访问特定资源', + permissions: [{ name: '只读 EC2' }, { name: '读写 S3' }, { name: '查看日志' }] }, { icon: '🎭', - name: '临时角色 (Role)', + name: '临时角色', scope: '按策略定义', - scenario: '跨账号访问、服务角色、临时授权', - permissions: [ - { name: '临时凭证 (1-12小时)', type: 'temp' }, - { name: '按信任策略授权', type: 'conditional' }, - { name: '可跨账号使用', type: 'cross' }, - { name: '无长期凭证', type: 'secure' } - ] + scenario: '跨账号访问、临时授权', + permissions: [{ name: '临时凭证' }, { name: '跨账号' }, { name: '无长期凭证' }] }, { icon: '🔑', - name: '服务账号 / 应用', - scope: 'API 访问权限', - scenario: '应用程序、CI/CD 流水线、自动化脚本', - permissions: [ - { name: 'AK/SK 或临时凭证', type: 'api' }, - { name: '特定服务 API 权限', type: 'service' }, - { name: '无控制台访问', type: 'programmatic' }, - { name: '建议定期轮换密钥', type: 'security' } - ] + name: '服务账号', + scope: 'API 访问', + scenario: '应用程序、CI/CD 流水线', + permissions: [{ name: 'AK/SK' }, { name: '特定 API' }, { name: '定期轮换' }] } ] -const selectedLevelData = computed(() => { - if (selectedLevel.value === null) return null - return hierarchyLevels[selectedLevel.value] -}) +const selectedLevelData = computed(() => hierarchyLevels[selectedLevel.value]) function selectLevel(index) { selectedLevel.value = index @@ -151,248 +100,102 @@ function selectLevel(index) { .permission-hierarchy-demo { border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 8px; - padding: 1.5rem; - margin: 1rem 0; - max-height: 600px; - overflow-y: auto; + border-radius: 6px; + padding: 0.75rem; + margin: 0.5rem 0; } .demo-header { - margin-bottom: 1rem; -} - -.demo-header h4 { - margin: 0 0 0.5rem 0; - font-weight: 800; - color: var(--vp-c-text-1); -} - -.intro-text { - margin: 0; - color: var(--vp-c-text-2); - font-size: 0.9rem; -} - -.demo-content { - margin-bottom: 1rem; -} - -.hierarchy-container { display: flex; - flex-direction: column; + align-items: center; gap: 0.5rem; - margin-bottom: 1.5rem; + margin-bottom: 0.75rem; } +.demo-header .icon { font-size: 1.25rem; } +.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; } + +.main-area { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.75rem; + margin-bottom: 0.75rem; +} + +@media (max-width: 640px) { + .main-area { grid-template-columns: 1fr; } +} + +.levels-list { display: flex; flex-direction: column; gap: 0.4rem; } + .level-row { display: flex; align-items: center; - gap: 0.75rem; - padding: 0.75rem 1rem; + gap: 0.5rem; + padding: 0.5rem; background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); border-radius: 6px; cursor: pointer; - transition: all 0.2s ease; + transition: all 0.2s; } -.level-row:hover, -.level-row.active { - background: var(--vp-c-bg-alt); - border-color: var(--vp-c-brand); - transform: translateX(4px); -} +.level-row:hover { border-color: var(--vp-c-brand); } +.level-row.active { border-color: var(--vp-c-brand); background: var(--vp-c-brand-soft); } -.level-icon { - font-size: 1.6rem; - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - border-radius: 6px; -} +.level-icon { font-size: 1.25rem; } -.level-content { - display: flex; - flex-direction: column; - flex: 1; -} - -.level-name { - font-weight: 600; - font-size: 0.95rem; - color: var(--vp-c-text-1); -} - -.level-scope { - font-size: 0.75rem; - color: var(--vp-c-text-3); -} - -.permission-badges { - display: flex; - gap: 0.25rem; - flex-wrap: wrap; - justify-content: flex-end; - max-width: 150px; -} - -.badge { - padding: 0.125rem 0.5rem; - background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - border-radius: 4px; - font-size: 0.65rem; - white-space: nowrap; - color: var(--vp-c-text-2); -} - -.badge.more { - background: var(--vp-c-brand-soft); - border-color: var(--vp-c-brand); - color: var(--vp-c-brand-1); -} +.level-info { display: flex; flex-direction: column; } +.level-name { font-weight: 600; font-size: 0.85rem; color: var(--vp-c-text-1); } +.level-scope { font-size: 0.7rem; color: var(--vp-c-text-2); } .detail-panel { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; - padding: 1rem; + border-radius: 6px; + padding: 0.75rem; } -.detail-panel h5 { - margin: 0 0 1rem 0; - font-size: 1.1rem; - font-weight: 700; +.detail-title { + font-weight: 600; + font-size: 0.9rem; color: var(--vp-c-brand-1); - padding-bottom: 0.5rem; + margin-bottom: 0.5rem; + padding-bottom: 0.4rem; border-bottom: 1px solid var(--vp-c-divider); } -.detail-section { - margin-bottom: 0.75rem; +.detail-row { display: flex; - align-items: flex-start; - gap: 0.5rem; + gap: 0.3rem; + margin-bottom: 0.3rem; + font-size: 0.8rem; } -.detail-section .label { - font-weight: 600; - color: var(--vp-c-text-2); - min-width: 80px; - font-size: 0.85rem; -} +.detail-row .label { color: var(--vp-c-text-2); } +.detail-row .value { color: var(--vp-c-text-1); } -.detail-section .value { - color: var(--vp-c-text-1); - font-size: 0.9rem; - flex: 1; -} - -.permissions-grid { - display: flex; - flex-wrap: wrap; - gap: 0.375rem; - flex: 1; -} +.perms-list { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.5rem; } .perm-tag { - padding: 0.25rem 0.625rem; - border-radius: 4px; font-size: 0.7rem; - font-weight: 500; -} - -.perm-tag.full { - background: rgba(var(--vp-c-brand-delta-rgb), 0.15); - color: var(--vp-c-brand-delta); -} - -.perm-tag.read, -.perm-tag.user, -.perm-tag.readonly { + padding: 0.15rem 0.4rem; background: var(--vp-c-brand-soft); color: var(--vp-c-brand-1); -} - -.perm-tag.limited, -.perm-tag.role { - background: rgba(var(--vp-c-brand-rgb), 0.1); - color: var(--vp-c-brand); -} - -.perm-tag.deny, -.perm-tag.critical { - background: rgba(var(--vp-c-brand-delta-rgb), 0.15); - color: var(--vp-c-brand-delta); -} - -.perm-tag.temp, -.perm-tag.conditional, -.perm-tag.service { - background: var(--vp-c-bg-soft); - border: 1px solid var(--vp-c-divider); - color: var(--vp-c-text-1); -} - -.perm-tag.admin, -.perm-tag.org, -.perm-tag.billing { - background: rgba(var(--vp-c-brand-rgb), 0.15); - color: var(--vp-c-brand); -} - -.perm-tag.api, -.perm-tag.programmatic, -.perm-tag.security { - background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - color: var(--vp-c-text-2); -} - -.perm-tag.cross, -.perm-tag.secure, -.perm-tag.audit, -.perm-tag.policy { - background: var(--vp-c-bg-soft); - border: 1px solid var(--vp-c-divider); - color: var(--vp-c-text-2); + border-radius: 3px; } .info-box { - padding: 0.75rem; background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - border-left: 4px solid var(--vp-c-brand); + padding: 0.6rem; border-radius: 6px; - font-size: 0.9rem; - line-height: 1.6; + font-size: 0.85rem; color: var(--vp-c-text-2); + display: flex; + gap: 0.25rem; } -.info-box strong { - color: var(--vp-c-text-1); -} - -@media (max-width: 768px) { - .level-row { - flex-wrap: wrap; - } - - .permission-badges { - width: 100%; - justify-content: flex-start; - max-width: none; - margin-top: 0.5rem; - } - - .detail-section { - flex-direction: column; - gap: 0.25rem; - } -} +.info-box .icon { flex-shrink: 0; } +.info-box strong { color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/PolicyEditorDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/PolicyEditorDemo.vue index 2e84e4f..e1a7d0c 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/PolicyEditorDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/PolicyEditorDemo.vue @@ -98,10 +98,10 @@ const effectList = computed(() => { diff --git a/docs/.vitepress/theme/components/appendix/cloud-services/ApiCallDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-services/ApiCallDemo.vue index 3833b91..a566f58 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-services/ApiCallDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-services/ApiCallDemo.vue @@ -103,10 +103,10 @@ function reset() { diff --git a/docs/.vitepress/theme/components/appendix/web-basics/CssCommonProperties.vue b/docs/.vitepress/theme/components/appendix/web-basics/CssCommonProperties.vue index 79d1d53..3f7ca8c 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/CssCommonProperties.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/CssCommonProperties.vue @@ -135,7 +135,7 @@ const categories = [ desc: '圆角', categoryLabel: '边框', fullDesc: '让盒子的角变圆润。现在的按钮通常都有点圆角。', - example: 'border-radius: 8px;' + example: 'border-radius: 6px;' }, { name: 'box-shadow', @@ -194,7 +194,7 @@ const categories = [ diff --git a/docs/.vitepress/theme/components/appendix/web-basics/CssLayoutDemo.vue b/docs/.vitepress/theme/components/appendix/web-basics/CssLayoutDemo.vue index cc07c4d..6003b30 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/CssLayoutDemo.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/CssLayoutDemo.vue @@ -183,7 +183,7 @@ const getItemColor = (n) => { diff --git a/docs/.vitepress/theme/components/appendix/web-basics/FrontendEvolutionDemo.vue b/docs/.vitepress/theme/components/appendix/web-basics/FrontendEvolutionDemo.vue index 6c0975e..99851f4 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/FrontendEvolutionDemo.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/FrontendEvolutionDemo.vue @@ -482,7 +482,7 @@ export default { } .editor-content { - padding: 1rem; + padding: 0.75rem; overflow: auto; flex: 1; } @@ -515,7 +515,7 @@ export default { background: white; border: 1px solid rgba(0, 0, 0, 0.1); padding: 0.8rem 1.2rem; - border-radius: 8px; + border-radius: 6px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); font-weight: 600; font-size: 0.9rem; diff --git a/docs/.vitepress/theme/components/appendix/web-basics/HttpExchangeDemo.vue b/docs/.vitepress/theme/components/appendix/web-basics/HttpExchangeDemo.vue index 0ef3ec4..10acfa7 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/HttpExchangeDemo.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/HttpExchangeDemo.vue @@ -192,9 +192,9 @@ const statusClass = computed(() => {