作者: HOS(安全风信子) 日期: 2026-05-25 主要来源平台: GitHub 摘要: 用户的第一次体验决定了产品的留存。本文讲解 Onboarding 的设计:渐进式功能引导、项目创建引导、AI 能力演示、以及如何通过 Onboarding 数据优化用户体验。还会讨论 AI IDE 特有的 Onboarding 挑战:如何让用户信任 AI 并学会与 AI 协作。
通过系统化的 Onboarding 设计方法论,帮助产品在用户首次接触的黄金窗口期内完成激活,显著提升留存率与转化率。 本节将从框架设计、交互模式、数据驱动三个维度,深入剖析如何构建一套高效的 AI IDE 用户引导体系。
Onboarding(用户引导与激活)是产品设计中最关键的环节之一,它决定了新用户在首次使用产品时的体验质量。从统计学角度看,用户留存曲线遵循著名的"40-20-10 法则"1:如果一个产品的日留存率为 40%,周留存率为 20%,月留存率为 10%,那么每增加一个用户,产品的病毒系数将达到一个健康的水平。
// 用户留存曲线计算模型
function calculateRetentionMetrics(dau, wau, mau) {
const weeklyRetention = dau / wau;
const monthlyRetention = dau / mau;
const mauEstimate = wau * 4; // 理想情况下 MAU = WAU * 4
return {
weeklyRetention: (weeklyRetention * 100).toFixed(2) + '%',
monthlyRetention: (monthlyRetention * 100).toFixed(2) + '%',
healthScore: dau > 1000 && weeklyRetention > 0.3 ? 'Healthy' : 'Needs Improvement'
};
}
// 示例:计算产品的留存指标
const metrics = calculateRetentionMetrics(5000, 15000, 45000);
console.log('Weekly Retention:', metrics.weeklyRetention);
console.log('Monthly Retention:', metrics.monthlyRetention);
console.log('Product Health:', metrics.healthScore);在 AI IDE 领域,Onboarding 的挑战更为复杂。传统软件的 Onboarding 只需要教会用户如何操作界面,而 AI IDE 还需要解决一个根本性问题:如何让用户信任 AI 并学会与 AI 协作。这是一个心理认知层面的挑战,需要从产品设计和交互设计两个角度同时发力。
Onboarding 的核心目标可以分解为以下几个层次:
目标层次 | 描述 | 衡量指标 | 目标值(AI IDE) |
|---|---|---|---|
认知目标 | 用户理解产品价值主张 | 价值认知率 | > 85% |
能力目标 | 用户掌握核心操作技能 | 任务完成率 | > 80% |
情感目标 | 用户建立对产品的信任感 | 信任评分 | > 4.2/5.0 |
行为目标 | 用户完成关键转化动作 | 激活率 | > 50% |
AI IDE 与传统 IDE 在 Onboarding 层面存在本质差异。传统 IDE 的功能相对稳定,用户学习的是具体的操作方式;而 AI IDE 的核心价值在于 AI 能力本身,这是一项不断演进且需要用户持续交互的技术。

这种分类型的 Onboarding 设计理念源于一个核心认知:不同背景的用户对于 AI IDE 的需求和恐惧点是不同的。有经验的程序员可能担心 AI 会替代他们的工作,而新手可能完全不知道如何使用 AI 来辅助编程。
在设计 Onboarding 框架时,我们面临一个经典的选择:渐进式引导(Progressive Disclosure)还是完整功能展示(Full Feature Revelation)?
渐进式引导的核心思想是只在用户需要时显示相关信息,而完整功能展示则倾向于在初始阶段就展示所有功能。两种方法各有优劣:
// 渐进式引导 vs 完整功能展示的对比实现
class OnboardingFramework {
constructor(type) {
this.type = type;
this.currentStep = 0;
this.completedSteps = new Set();
}
}
// 渐进式引导框架
class ProgressiveOnboarding extends OnboardingFramework {
constructor() {
super('progressive');
this.contextualTriggers = new Map();
}
// 基于上下文触发引导
shouldTriggerStep(stepName, userContext) {
const trigger = this.contextualTriggers.get(stepName);
if (!trigger) return false;
return trigger(userContext);
}
// 仅在用户尝试某功能时显示相关帮助
registerContextualHelp(stepName, triggerCondition, helpContent) {
this.contextualTriggers.set(stepName, triggerCondition);
return this;
}
getNextStep(userContext) {
const steps = ['welcome', 'project_create', 'ai_basics', 'first_completion'];
while (this.currentStep < steps.length) {
const step = steps[this.currentStep];
if (this.shouldTriggerStep(step, userContext)) {
return { step, content: this.getStepContent(step) };
}
this.currentStep++;
}
return null; // 所有上下文引导已完成
}
}
// 完整功能展示框架
class FullFeatureOnboarding extends OnboardingFramework {
constructor() {
super('full_feature');
this.allSteps = [
{ name: 'welcome', mandatory: true },
{ name: 'feature_overview', mandatory: true },
{ name: 'project_templates', mandatory: true },
{ name: 'ai_introduction', mandatory: true },
{ name: 'collaboration_mode', mandatory: true },
{ name: 'first_project', mandatory: true },
{ name: 'completion_celebration', mandatory: true }
];
}
getAllSteps() {
return this.allSteps.map(step => ({
...step,
content: this.getStepContent(step.name)
}));
}
// 必须完成所有步骤才能进入主界面
validateCompletion() {
return this.completedSteps.size === this.allSteps.length;
}
}维度 | 渐进式引导 | 完整功能展示 |
|---|---|---|
用户控制感 | 高 | 低 |
完成率 | 较高(用户可跳过) | 较低(流程较长) |
认知负担 | 低(每次只处理一件事) | 高(信息量大) |
适用场景 | 功能复杂的产品 | 功能简单但需要全面了解的产品 |
灵活性 | 高 | 低 |
基于对用户旅程的深入分析,我们提出一种分层 Onboarding 架构,该架构将 Onboarding 分为四个层次,每个层次解决不同层次的用户需求:

模型调优
这种分层设计的核心理念是:用户的 Onboarding 旅程应该是可中断、可恢复、可定制的。用户可以根据自己的需求选择进入哪个层次,而不必按照固定的顺序完成所有步骤。
// 分层 Onboarding 引擎
class LayeredOnboardingEngine {
constructor() {
this.layers = {
value_perception: {
level: 1,
steps: ['welcome_video', 'ai_demo', 'persona_selection'],
completionCriteria: (user) => user.watchedDemo && user.selectedPersona
},
core_capability: {
level: 2,
steps: ['project_creation', 'basic_editing', 'first_ai_request'],
completionCriteria: (user) => user.completedProject && user.madeFirstAIRequest
},
deep_feature: {
level: 3,
steps: ['debugging', 'ai_advanced', 'collaboration'],
completionCriteria: (user) => user.usedDebugger && user.collaborated
},
advanced_tips: {
level: 4,
steps: ['shortcuts', 'customization', 'model_tuning'],
completionCriteria: (user) => user.learnedShortcuts && user.customizedUI
}
};
this.userProgress = new Map();
}
// 获取用户当前应该处于的层级
getCurrentLayer(userId) {
const progress = this.userProgress.get(userId);
if (!progress) return 'value_perception';
for (const [layerName, layer] of Object.entries(this.layers)) {
if (!layer.completionCriteria(progress)) {
return layerName;
}
}
return 'completed';
}
// 获取当前层级的下一步
getNextStepInLayer(userId) {
const currentLayer = this.getCurrentLayer(userId);
const layer = this.layers[currentLayer];
const progress = this.userProgress.get(userId) || {};
const completedSteps = progress.completedSteps || new Set();
for (const step of layer.steps) {
if (!completedSteps.has(step)) {
return { layer: currentLayer, step, content: this.getStepContent(step) };
}
}
return null; // 当前层级已完成
}
// 用户完成一个步骤
completeStep(userId, step) {
const progress = this.userProgress.get(userId) || {};
progress.completedSteps = progress.completedSteps || new Set();
progress.completedSteps.add(step);
this.userProgress.set(userId, progress);
// 检查是否应该解锁新层级
const currentLayer = this.getCurrentLayer(userId);
const layer = this.layers[currentLayer];
if (layer.completionCriteria(progress)) {
this.unlockNextLayer(userId, currentLayer);
}
}
}Tooltips 是最常见的用户引导形式,它以非侵入式的方式在用户需要时提供即时的上下文帮助。一个设计良好的 Tooltips 系统应该具备以下特性:
// Tooltips 引导系统核心实现
class TooltipSystem {
constructor(options = {}) {
this.tooltips = new Map();
this.activeTooltip = null;
this.positioningStrategy = options.positioningStrategy || 'smart';
this.delay = options.delay || 300;
this.timeout = options.timeout || 5000;
}
// 注册 Tooltip
registerTooltip(elementId, content, options = {}) {
this.tooltips.set(elementId, {
content,
position: options.position || 'bottom',
trigger: options.trigger || 'hover', // hover, click, manual
delay: options.delay || this.delay,
dismissible: options.dismissible ?? true,
overlay: options.overlay ?? false, // 是否显示遮罩引导
highlight: options.highlight ?? false // 是否高亮目标元素
});
}
// 智能定位:避免超出视口
calculateSmartPosition(element, preferredPosition) {
const rect = element.getBoundingClientRect();
const viewport = {
width: window.innerWidth,
height: window.innerHeight
};
const positions = ['top', 'bottom', 'left', 'right'];
const positionMap = {
top: { x: rect.left + rect.width / 2, y: rect.top },
bottom: { x: rect.left + rect.width / 2, y: rect.bottom },
left: { x: rect.left, y: rect.top + rect.height / 2 },
right: { x: rect.right, y: rect.top + rect.height / 2 }
};
// 检查每个位置是否可见
for (const pos of positions) {
const posCoords = positionMap[pos];
if (this.isPositionVisible(posCoords, viewport)) {
return pos;
}
}
return preferredPosition; // 回退到首选位置
}
isPositionVisible(coords, viewport) {
const margin = 10;
return coords.x > margin &&
coords.x < viewport.width - margin &&
coords.y > margin &&
coords.y < viewport.height - margin;
}
// 显示 Tooltip
showTooltip(elementId) {
const tooltip = this.tooltips.get(elementId);
if (!tooltip) return;
const element = document.getElementById(elementId);
if (!element) return;
// 如果需要遮罩引导,先创建遮罩
if (tooltip.overlay) {
this.createOverlay(element);
}
// 如果需要高亮,先高亮元素
if (tooltip.highlight) {
this.highlightElement(element);
}
// 计算位置
const position = this.calculateSmartPosition(element, tooltip.position);
// 创建 Tooltip DOM
const tooltipEl = this.createTooltipElement(tooltip, position);
document.body.appendChild(tooltipEl);
this.activeTooltip = tooltipEl;
// 设置自动消失
if (tooltip.timeout > 0) {
setTimeout(() => {
if (this.activeTooltip === tooltipEl) {
this.hideTooltip();
}
}, tooltip.timeout);
}
}
createOverlay(targetElement) {
const overlay = document.createElement('div');
overlay.className = 'onboarding-overlay';
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
z-index: 9998;
pointer-events: none;
`;
// 在目标元素处创建透明孔洞
const rect = targetElement.getBoundingClientRect();
const hole = document.createElement('div');
hole.style.cssText = `
position: absolute;
top: ${rect.top - 10}px;
left: ${rect.left - 10}px;
width: ${rect.width + 20}px;
height: ${rect.height + 20}px;
background: transparent;
border: 2px solid #4A90E2;
border-radius: 8px;
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.6);
`;
overlay.appendChild(hole);
document.body.appendChild(overlay);
return overlay;
}
createTooltipElement(tooltip, position) {
const el = document.createElement('div');
el.className = 'onboarding-tooltip';
el.innerHTML = `
<div class="tooltip-content">${tooltip.content}</div>
${tooltip.dismissible ? '<button class="tooltip-dismiss">×</button>' : ''}
`;
const offset = 15;
el.style.cssText = `
position: fixed;
z-index: 9999;
background: #2D3748;
color: white;
padding: 16px 20px;
border-radius: 8px;
font-size: 14px;
max-width: 320px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
animation: tooltipFadeIn 0.2s ease-out;
`;
// 定位逻辑
const targetEl = document.querySelector(`[data-tooltip-id]`);
if (targetEl) {
const rect = targetEl.getBoundingClientRect();
const positions = {
top: { top: rect.top - offset, left: rect.left + rect.width / 2 },
bottom: { top: rect.bottom + offset, left: rect.left + rect.width / 2 },
left: { top: rect.top + rect.height / 2, left: rect.left - offset },
right: { top: rect.top + rect.height / 2, left: rect.right + offset }
};
Object.assign(el.style, positions[position]);
}
return el;
}
hideTooltip() {
if (this.activeTooltip) {
this.activeTooltip.remove();
this.activeTooltip = null;
}
// 移除遮罩
document.querySelectorAll('.onboarding-overlay').forEach(el => el.remove());
document.querySelectorAll('.onboarding-highlight').forEach(el => {
el.classList.remove('onboarding-highlight');
});
}
}视频教程是传达复杂信息的有效方式,特别适合展示 AI IDE 的核心功能和价值主张。一个完善的视频教程体系应该包含以下层次:
视频类型 | 时长 | 目标用户 | 核心目标 |
|---|---|---|---|
产品概览视频 | 60-90秒 | 所有新用户 | 传达核心价值 |
功能演示视频 | 3-5分钟 | 特定功能探索者 | 展示具体操作 |
深度教程 | 10-15分钟 | 进阶用户 | 掌握高级技巧 |
AI 协作指南 | 5-8分钟 | 所有用户 | 学会与 AI 协作 |
// 视频教程播放系统
class VideoTutorialSystem {
constructor() {
this.tutorials = new Map();
this.userProgress = new Map();
this.currentVideo = null;
}
// 注册视频教程
registerTutorial(id, tutorial) {
this.tutorials.set(id, {
...tutorial,
watchedPercentage: 0,
completed: false,
bookmarked: false,
lastPosition: 0
});
}
// 播放视频
play(tutorialId) {
const tutorial = this.tutorials.get(tutorialId);
if (!tutorial) return null;
this.currentVideo = {
id: tutorialId,
startTime: tutorial.lastPosition,
playlist: this.getPlaylist(tutorial.category)
};
return {
videoUrl: tutorial.videoUrl,
startTime: tutorial.lastPosition,
chapters: tutorial.chapters,
onProgress: (percent) => this.updateProgress(tutorialId, percent),
onComplete: () => this.markComplete(tutorialId)
};
}
// 获取播放列表(同类别视频)
getPlaylist(category) {
const playlist = [];
for (const [id, tutorial] of this.tutorials) {
if (tutorial.category === category) {
playlist.push({ id, title: tutorial.title, duration: tutorial.duration });
}
}
return playlist;
}
// 更新观看进度
updateProgress(tutorialId, percentage) {
const tutorial = this.tutorials.get(tutorialId);
if (tutorial) {
tutorial.watchedPercentage = Math.max(tutorial.watchedPercentage, percentage);
// 保存观看位置
if (percentage > 0) {
const userId = this.getCurrentUserId();
this.userProgress.set(`${userId}_${tutorialId}`, {
lastPosition: percentage,
updatedAt: new Date()
});
}
}
}
// 标记为已完成
markComplete(tutorialId) {
const tutorial = this.tutorials.get(tutorialId);
if (tutorial) {
tutorial.completed = true;
tutorial.watchedPercentage = 100;
// 触发下一步推荐
this.recommendNext(tutorialId);
}
}
// 推荐下一个视频
recommendNext(completedTutorialId) {
const completed = this.tutorials.get(completedTutorialId);
const playlist = this.getPlaylist(completed.category);
// 找到下一个未观看的视频
for (const video of playlist) {
const tutorial = this.tutorials.get(video.id);
if (!tutorial.completed) {
return { id: video.id, title: video.title, reason: 'Up Next' };
}
}
// 播放列表已完成,推荐其他类别
return this.recommendCrossCategory(completed.category);
}
recommendCrossCategory(excludeCategory) {
for (const [id, tutorial] of this.tutorials) {
if (tutorial.category !== excludeCategory && !tutorial.completed) {
return { id, title: tutorial.title, reason: 'Expand Your Skills' };
}
}
return null;
}
}交互式教程(Interactive Tutorial)是一种革命性的用户引导方式,它允许用户在真实的产品环境中边学边做。与视频教程不同,交互式教程能够:

// 交互式教程引擎
class InteractiveTutorialEngine {
constructor() {
this.tutorials = new Map();
this.activeTutorial = null;
this.stepResults = [];
this.hooks = {
onStepComplete: null,
onTutorialComplete: null,
onError: null
};
}
// 注册教程
registerTutorial(tutorial) {
this.tutorials.set(tutorial.id, {
...tutorial,
steps: tutorial.steps.map((step, index) => ({
...step,
order: index,
status: 'pending' // pending, active, completed, skipped
}))
});
}
// 开始教程
startTutorial(tutorialId) {
const tutorial = this.tutorials.get(tutorialId);
if (!tutorial) throw new Error(`Tutorial ${tutorialId} not found`);
this.activeTutorial = {
id: tutorialId,
currentStepIndex: 0,
startTime: Date.now()
};
this.stepResults = [];
this.activateStep(0);
return this.getTutorialState();
}
// 激活特定步骤
activateStep(stepIndex) {
const tutorial = this.tutorials.get(this.activeTutorial.id);
const step = tutorial.steps[stepIndex];
// 重置所有步骤状态
tutorial.steps.forEach((s, i) => {
s.status = i < stepIndex ? 'completed' : (i === stepIndex ? 'active' : 'pending');
});
// 发送教程状态到 UI
this.broadcastTutorialState();
// 如果步骤有目标选择器,高亮目标元素
if (step.targetSelector) {
this.highlightTarget(step.targetSelector);
}
// 如果步骤有模拟输入,设置模拟状态
if (step.simulatedInput) {
this.setSimulatedInput(step.simulatedInput);
}
}
// 处理用户操作
handleUserAction(action) {
if (!this.activeTutorial) return null;
const tutorial = this.tutorials.get(this.activeTutorial.id);
const currentStep = tutorial.steps[this.activeTutorial.currentStepIndex];
// 验证操作是否符合预期
const validation = this.validateAction(action, currentStep);
if (validation.valid) {
return this.completeStep(validation.feedback);
} else {
return this.showError(validation.message);
}
}
// 验证操作
validateAction(action, step) {
// 检查操作类型
if (step.expectedAction && step.expectedAction.type !== action.type) {
return { valid: false, message: `Expected ${step.expectedAction.type}, got ${action.type}` };
}
// 检查目标元素
if (step.targetSelector && action.target !== step.targetSelector) {
return { valid: false, message: `Wrong target element` };
}
// 检查输入值
if (step.expectedAction && step.expectedAction.value) {
if (action.value !== step.expectedAction.value) {
return { valid: false, message: `Expected value "${step.expectedAction.value}"` };
}
}
return { valid: true, feedback: step.successFeedback || 'Great job!' };
}
// 完成当前步骤
completeStep(feedback) {
const tutorial = this.tutorials.get(this.activeTutorial.id);
const currentStep = tutorial.steps[this.activeTutorial.currentStepIndex];
currentStep.status = 'completed';
this.stepResults.push({
step: currentStep.order,
success: true,
feedback,
timestamp: Date.now()
});
// 触发钩子
if (this.hooks.onStepComplete) {
this.hooks.onStepComplete(currentStep);
}
// 检查是否还有更多步骤
if (this.activeTutorial.currentStepIndex < tutorial.steps.length - 1) {
this.activeTutorial.currentStepIndex++;
this.activateStep(this.activeTutorial.currentStepIndex);
} else {
return this.completeTutorial();
}
return this.getTutorialState();
}
// 显示错误
showError(message) {
const tutorial = this.tutorials.get(this.activeTutorial.id);
const currentStep = tutorial.steps[this.activeTutorial.currentStepIndex];
this.stepResults.push({
step: currentStep.order,
success: false,
error: message,
timestamp: Date.now()
});
if (this.hooks.onError) {
this.hooks.onError(message, currentStep);
}
return {
type: 'error',
message,
hint: currentStep.errorHint || 'Try again!'
};
}
// 完成教程
completeTutorial() {
const tutorial = this.tutorials.get(this.activeTutorial.id);
tutorial.completed = true;
tutorial.completedAt = Date.now();
tutorial.duration = Date.now() - this.activeTutorial.startTime;
this.activeTutorial = null;
if (this.hooks.onTutorialComplete) {
this.hooks.onTutorialComplete(tutorial);
}
return {
type: 'tutorial_complete',
tutorialId: tutorial.id,
duration: tutorial.duration,
stepResults: this.stepResults
};
}
// 获取教程状态
getTutorialState() {
if (!this.activeTutorial) return null;
const tutorial = this.tutorials.get(this.activeTutorial.id);
const currentStep = tutorial.steps[this.activeTutorial.currentStepIndex];
return {
tutorialId: tutorial.id,
tutorialTitle: tutorial.title,
currentStep: {
index: this.activeTutorial.currentStepIndex,
title: currentStep.title,
instruction: currentStep.instruction,
hint: currentStep.hint,
targetSelector: currentStep.targetSelector
},
progress: {
current: this.activeTutorial.currentStepIndex + 1,
total: tutorial.steps.length,
percentage: ((this.activeTutorial.currentStepIndex + 1) / tutorial.steps.length) * 100
},
completedSteps: this.stepResults.filter(r => r.success).length
};
}
}AI IDE 的核心竞争力在于其 AI 能力,因此 Onboarding 流程中必须包含能够让用户快速体验 AI 价值的环节。根据用户的认知心理学研究,人们对一个产品的价值感知往往在最初 30 秒内形成,这意味着 AI 演示的质量直接影响用户对整个产品的认知。

不同用户对于 AI 的接受度和信任度是不同的,因此 AI 演示应该采用分层策略:
演示层级 | 适用用户 | 演示内容 | 交互深度 | 目标信任度 |
|---|---|---|---|---|
Level 1: 观察 | 高度怀疑者 | AI 静默运行,用户观察 | 低 | 建立初步认知 |
Level 2: 参与 | 谨慎观望者 | AI 执行,用户确认 | 中 | 建立基本信任 |
Level 3: 协作 | 开放尝试者 | AI 建议,用户决策 | 高 | 建立协作信心 |
Level 4: 依赖 | 积极采用者 | AI 主导,用户微调 | 极高 | 建立使用习惯 |
// AI 演示引擎
class AIDemoEngine {
constructor() {
this.demos = new Map();
this.userTrustLevel = new Map();
this.demoHistory = new Map();
}
// 注册演示场景
registerDemo(demo) {
this.demos.set(demo.id, {
...demo,
minTrustLevel: demo.minTrustLevel || 1,
maxTrustLevel: demo.maxTrustLevel || 4
});
}
// 获取适合用户的演示
getAppropriateDemo(userId) {
const trustLevel = this.userTrustLevel.get(userId) || 1;
// 找到信任级别匹配且用户未完成的演示
const candidates = [];
for (const [id, demo] of this.demos) {
if (demo.minTrustLevel <= trustLevel &&
demo.maxTrustLevel >= trustLevel &&
!this.hasCompletedDemo(userId, id)) {
candidates.push(demo);
}
}
// 按信任级别匹配度排序
candidates.sort((a, b) => {
const aMatch = a.minTrustLevel <= trustLevel && a.maxTrustLevel >= trustLevel;
const bMatch = b.minTrustLevel <= trustLevel && b.maxTrustLevel >= trustLevel;
return bMatch - aMatch;
});
return candidates[0] || null;
}
// 执行演示
async executeDemo(userId, demoId) {
const demo = this.demos.get(demoId);
if (!demo) throw new Error(`Demo ${demoId} not found`);
const trustLevel = this.userTrustLevel.get(userId) || 1;
if (trustLevel < demo.minTrustLevel) {
throw new Error(`User trust level ${trustLevel} below minimum ${demo.minTrustLevel}`);
}
// 记录演示开始
this.recordDemoStart(userId, demoId);
// 根据信任级别选择执行模式
const mode = this.getDemoMode(trustLevel);
// 执行演示
const result = await demo.execute(mode);
// 记录演示结果
this.recordDemoResult(userId, demoId, result);
// 根据结果调整信任级别
this.updateTrustLevel(userId, result);
return result;
}
// 根据信任级别获取演示模式
getDemoMode(trustLevel) {
const modes = {
1: 'observe', // 观察模式:用户只能看
2: 'participate', // 参与模式:用户确认 AI 决策
3: 'collaborate', // 协作模式:用户与 AI 共同决策
4: 'delegate' // 委托模式:用户授权 AI 执行
};
return modes[trustLevel] || 'observe';
}
// 记录演示开始
recordDemoStart(userId, demoId) {
const history = this.demoHistory.get(userId) || [];
history.push({
demoId,
startTime: Date.now(),
status: 'in_progress'
});
this.demoHistory.set(userId, history);
}
// 记录演示结果
recordDemoResult(userId, demoId, result) {
const history = this.demoHistory.get(userId) || [];
const current = history[history.length - 1];
current.endTime = Date.now();
current.status = result.success ? 'completed' : 'failed';
current.userSatisfaction = result.satisfaction;
current.trustDelta = result.trustDelta || 0;
}
// 检查用户是否已完成演示
hasCompletedDemo(userId, demoId) {
const history = this.demoHistory.get(userId) || [];
return history.some(h => h.demoId === demoId && h.status === 'completed');
}
// 更新信任级别
updateTrustLevel(userId, result) {
const current = this.userTrustLevel.get(userId) || 1;
const delta = result.trustDelta || 0;
const newLevel = Math.max(1, Math.min(4, current + delta));
this.userTrustLevel.set(userId, newLevel);
}
}在 AI IDE 的 Onboarding 过程中,建立用户对 AI 的信任是核心挑战。用户对 AI 的信任受到多种因素影响,包括但不限于:
根据 Mayer 等人的研究2,信任由三个维度构成:能力(Ability)、善意(Benevolence)、正直(Integrity)。
// AI 信任模型
class AITrustModel {
constructor() {
this.trustComponents = {
ability: { weight: 0.4, score: 0 },
benevolence: { weight: 0.3, score: 0 },
integrity: { weight: 0.3, score: 0 }
};
}
// 更新能力信任
updateAbilityTrust(successCount, totalAttempts) {
const successRate = successCount / totalAttempts;
const consistency = this.calculateConsistency(successCount, totalAttempts);
// 能力信任 = 成功率 * 0.6 + 一致性 * 0.4
this.trustComponents.ability.score = successRate * 0.6 + consistency * 0.4;
}
// 计算一致性(避免大幅波动)
calculateConsistency(successCount, totalAttempts) {
if (totalAttempts < 5) return 0.5; // 数据不足时返回中性值
// 计算最近 N 次的成功率趋势
const recentWindow = 5;
const recentSuccessRate = successCount / totalAttempts;
const baseline = this.trustComponents.ability.score;
// 一致性 = 1 - |当前成功率 - 基准分| / 2
return Math.max(0, 1 - Math.abs(recentSuccessRate - baseline) / 2);
}
// 更新善意信任
updateBenevolenceTrust(collaborativeInteractions, conflictResolutions) {
// 善意信任建立在 AI 在冲突中站在用户这边的次数
const collaborationRate = collaborativeInteractions /
(collaborativeInteractions + conflictResolutions);
// 冲突解决率:如果 AI 在冲突中给出有益建议
const beneficialResolutionRate = conflictResolutions > 0
? collaborativeInteractions / conflictResolutions
: 1;
this.trustComponents.benevolence.score =
collaborationRate * 0.5 + beneficialResolutionRate * 0.5;
}
// 更新正直信任
updateIntegrityTrust(transparencyScore, errorAcknowledgmentRate) {
// 正直信任 = 透明度得分 * 0.5 + 错误承认率 * 0.5
this.trustComponents.integrity.score =
transparencyScore * 0.5 + errorAcknowledgmentRate * 0.5;
}
// 计算综合信任分数
calculateOverallTrust() {
const components = this.trustComponents;
return (
components.ability.score * components.ability.weight +
components.benevolence.score * components.benevolence.weight +
components.integrity.score * components.integrity.weight
);
}
// 获取信任等级描述
getTrustLevel() {
const trust = this.calculateOverallTrust();
if (trust >= 0.8) return 'High Trust';
if (trust >= 0.6) return 'Moderate Trust';
if (trust >= 0.4) return 'Low Trust';
return 'Distrust';
}
// 获取信任改进建议
getImprovementSuggestions() {
const suggestions = [];
const components = this.trustComponents;
if (components.ability.score < 0.6) {
suggestions.push({
component: 'ability',
priority: 'high',
suggestion: 'Increase AI success rate through better context understanding'
});
}
if (components.benevolence.score < 0.6) {
suggestions.push({
component: 'benevolence',
priority: 'medium',
suggestion: 'Show more collaborative behavior and user-aligned suggestions'
});
}
if (components.integrity.score < 0.6) {
suggestions.push({
component: 'integrity',
priority: 'medium',
suggestion: 'Improve transparency in AI decision-making process'
});
}
return suggestions;
}
}衡量 Onboarding 效果需要一套完整的指标体系。这套指标体系应该覆盖从用户首次访问到完成激活的完整旅程:
指标名称 | 定义 | 计算方式 | 目标值 |
|---|---|---|---|
注册到首次使用 | 用户注册到首次使用产品的时间 | T(first_use) - T(signup) | < 5 分钟 |
首次任务完成率 | 首次使用即完成核心任务的用户比例 | N(completed) / N(first_session) | > 60% |
Onboarding 完成率 | 完成全部 Onboarding 步骤的用户比例 | N(completed_onboarding) / N(started) | > 50% |
激活率 | 达成"激活"定义的用户比例 | N(activated) / N(signup) | > 40% |
7 日留存率 | 7 天后仍回访的用户比例 | N(D7) / N(signup) | > 30% |
Onboarding 转化时间 | 完成 Onboarding 所需的平均时间 | AVG(T(completion) - T(start)) | < 15 分钟 |
// 激活指标追踪系统
class ActivationTracker {
constructor() {
this.events = [];
this.userStates = new Map();
this.metrics = new Map();
}
// 记录事件
trackEvent(userId, event) {
this.events.push({
userId,
...event,
timestamp: Date.now()
});
// 更新用户状态
this.updateUserState(userId, event);
// 实时更新指标
this.updateMetrics(event);
}
// 追踪首次使用
trackFirstUse(userId) {
this.trackEvent(userId, {
type: 'first_use',
timeSinceSignup: this.getTimeSinceSignup(userId)
});
}
// 追踪 Onboarding 步骤完成
trackOnboardingStep(userId, stepName, stepDuration) {
this.trackEvent(userId, {
type: 'onboarding_step_completed',
step: stepName,
duration: stepDuration
});
}
// 追踪激活
trackActivation(userId, activationMethod) {
this.trackEvent(userId, {
type: 'activated',
method: activationMethod,
timeToActivate: this.getTimeSinceSignup(userId)
});
}
// 获取用户状态
getUserState(userId) {
return this.userStates.get(userId) || {
signupTime: null,
firstUseTime: null,
onboardingStartTime: null,
onboardingCompleted: false,
activated: false,
activationTime: null,
completedSteps: []
};
}
// 更新用户状态
updateUserState(userId, event) {
const state = this.getUserState(userId);
switch (event.type) {
case 'signup':
state.signupTime = event.timestamp;
break;
case 'first_use':
state.firstUseTime = event.timestamp;
break;
case 'onboarding_started':
state.onboardingStartTime = event.timestamp;
break;
case 'onboarding_step_completed':
state.completedSteps.push({
step: event.step,
timestamp: event.timestamp,
duration: event.duration
});
break;
case 'onboarding_completed':
state.onboardingCompleted = true;
state.onboardingCompletedTime = event.timestamp;
break;
case 'activated':
state.activated = true;
state.activationTime = event.timestamp;
break;
}
this.userStates.set(userId, state);
}
// 计算核心指标
calculateMetrics(dateRange = null) {
const filteredEvents = dateRange
? this.filterEventsByDateRange(dateRange)
: this.events;
const users = new Set(filteredEvents.map(e => e.userId));
return {
signupToFirstUse: this.calculateSignupToFirstUse(filteredEvents),
firstTaskCompletionRate: this.calculateFirstTaskCompletionRate(filteredEvents),
onboardingCompletionRate: this.calculateOnboardingCompletionRate(filteredEvents),
activationRate: this.calculateActivationRate(filteredEvents),
retentionRates: this.calculateRetentionRates(filteredEvents),
onboardingDuration: this.calculateOnboardingDuration(filteredEvents)
};
}
// 计算注册到首次使用时间
calculateSignupToFirstUse(events) {
const signupEvents = events.filter(e => e.type === 'signup');
const firstUseEvents = events.filter(e => e.type === 'first_use');
const times = [];
for (const signup of signupEvents) {
const firstUse = firstUseEvents.find(
e => e.userId === signup.userId && e.timestamp > signup.timestamp
);
if (firstUse) {
times.push(firstUse.timeSinceSignup);
}
}
return {
average: times.length > 0 ? times.reduce((a, b) => a + b, 0) / times.length : null,
median: this.median(times),
p95: this.percentile(times, 95)
};
}
// 计算首次任务完成率
calculateFirstTaskCompletionRate(events) {
const usersWithFirstUse = new Set(
events.filter(e => e.type === 'first_use').map(e => e.userId)
);
const usersWithTaskCompletion = new Set(
events.filter(e => e.type === 'first_task_completed').map(e => e.userId)
);
let count = 0;
for (const userId of usersWithFirstUse) {
if (usersWithTaskCompletion.has(userId)) {
count++;
}
}
return usersWithFirstUse.size > 0
? count / usersWithFirstUse.size
: 0;
}
// 计算 Onboarding 完成率
calculateOnboardingCompletionRate(events) {
const started = events.filter(e => e.type === 'onboarding_started');
const completed = events.filter(e => e.type === 'onboarding_completed');
const startedUsers = new Set(started.map(e => e.userId));
const completedUsers = new Set(completed.map(e => e.userId));
let count = 0;
for (const userId of startedUsers) {
if (completedUsers.has(userId)) {
count++;
}
}
return startedUsers.size > 0 ? count / startedUsers.size : 0;
}
// 辅助方法
median(arr) {
if (arr.length === 0) return null;
const sorted = [...arr].sort((a, b) => a - b);
const mid = Math.floor(sorted.length / 2);
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
}
percentile(arr, p) {
if (arr.length === 0) return null;
const sorted = [...arr].sort((a, b) => a - b);
const index = Math.ceil((p / 100) * sorted.length) - 1;
return sorted[index];
}
}日活跃用户(DAU)、周活跃用户(WAU)和月活跃用户(MAU)是衡量产品健康度的核心指标。在 Onboarding 优化过程中,我们需要特别关注这些指标的变化趋势:
// DAU/WAU/MAU 监控系统
class DAUWAUMAUMonitor {
constructor() {
this.activeUsers = {
daily: new Map(),
weekly: new Map(),
monthly: new Map()
};
}
// 记录用户活跃
recordActivity(userId, timestamp = Date.now()) {
const date = new Date(timestamp);
// 记录日活跃
const dailyKey = this.getDateKey(date);
this.addToSet(this.activeUsers.daily, dailyKey, userId);
// 记录周活跃
const weeklyKey = this.getWeekKey(date);
this.addToSet(this.activeUsers.weekly, weeklyKey, userId);
// 记录月活跃
const monthlyKey = this.getMonthKey(date);
this.addToSet(this.activeUsers.monthly, monthlyKey, userId);
}
// 获取 DAU
getDAU(date) {
const key = this.getDateKey(date);
return this.activeUsers.daily.get(key)?.size || 0;
}
// 获取 WAU
getWAU(date) {
const weekKey = this.getWeekKey(date);
return this.activeUsers.weekly.get(weekKey)?.size || 0;
}
// 获取 MAU
getMAU(date) {
const monthKey = this.getMonthKey(date);
return this.activeUsers.monthly.get(monthKey)?.size || 0;
}
// 计算 DAU/MAU 比率(魔力黏性指标)
getDAUtoMAURatio(date) {
const dau = this.getDAU(date);
const mau = this.getMAU(date);
return mau > 0 ? dau / mau : 0;
}
// 计算 WAU/MAU 比率
getWAUtoMAURatio(date) {
const wau = this.getWAU(date);
const mau = this.getMAU(date);
return mau > 0 ? wau / mau : 0;
}
// 获取活跃趋势
getTrend(metric, days) {
const trend = [];
const now = new Date();
for (let i = days - 1; i >= 0; i--) {
const date = new Date(now);
date.setDate(date.getDate() - i);
let value;
switch (metric) {
case 'dau':
value = this.getDAU(date);
break;
case 'wau':
value = this.getWAU(date);
break;
case 'mau':
value = this.getMAU(date);
break;
}
trend.push({
date: this.getDateKey(date),
value
});
}
return trend;
}
// Onboarding 质量对活跃度的影响分析
analyzeOnboardingImpact() {
// 计算不同 Onboarding 完成状态用户的活跃度
const cohorts = {
completed: { daily: [], weekly: [], monthly: [] },
partial: { daily: [], weekly: [], monthly: [] },
abandoned: { daily: [], weekly: [], monthly: [] }
};
// 分析逻辑...
return {
completed: this.calculateCohortEngagement(cohorts.completed),
partial: this.calculateCohortEngagement(cohorts.partial),
abandoned: this.calculateCohortEngagement(cohorts.abandoned)
};
}
// 辅助方法
getDateKey(date) {
return date.toISOString().split('T')[0];
}
getWeekKey(date) {
const year = date.getFullYear();
const week = this.getWeekNumber(date);
return `${year}-W${week.toString().padStart(2, '0')}`;
}
getMonthKey(date) {
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}`;
}
getWeekNumber(date) {
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
const dayNum = d.getUTCDay() || 7;
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
}
addToSet(map, key, value) {
if (!map.has(key)) {
map.set(key, new Set());
}
map.get(key).add(value);
}
}A/B 测试是优化 Onboarding 流程的核心方法。通过科学的实验设计,我们可以量化不同 Onboarding 方案的效果差异,从而做出数据驱动的决策。
// Onboarding A/B 测试框架
class OnboardingABTester {
constructor() {
this.experiments = new Map();
this.assignments = new Map();
this.conversions = new Map();
}
// 创建实验
createExperiment(config) {
const experiment = {
id: config.id,
name: config.name,
hypothesis: config.hypothesis,
variants: config.variants, // { control: {...}, treatment: {...} }
metric: config.metric, // 优化指标
target: config.target || 0.05, // 最小可检测效果
confidence: config.confidence || 0.95, // 置信水平
status: 'draft',
startTime: null,
endTime: null,
samples: { control: 0, treatment: 0 },
results: { control: 0, treatment: 0 }
};
this.experiments.set(config.id, experiment);
return experiment;
}
// 启动实验
startExperiment(experimentId) {
const experiment = this.experiments.get(experimentId);
if (!experiment) throw new Error(`Experiment ${experimentId} not found`);
experiment.status = 'running';
experiment.startTime = Date.now();
}
// 用户分配到实验组
assignUser(experimentId, userId) {
// 检查用户是否已有分配
const existingAssignment = this.assignments.get(`${experimentId}_${userId}`);
if (existingAssignment) return existingAssignment;
const experiment = this.experiments.get(experimentId);
if (!experiment || experiment.status !== 'running') return null;
// 哈希用户 ID 以确保随机但一致的分配
const hash = this.hash(`${experimentId}_${userId}`);
const variant = hash % 2 === 0 ? 'control' : 'treatment';
const assignment = {
experimentId,
userId,
variant,
assignedAt: Date.now()
};
this.assignments.set(`${experimentId}_${userId}`, assignment);
experiment.samples[variant]++;
return assignment;
}
// 记录转化
recordConversion(experimentId, userId, value = 1) {
const assignment = this.assignments.get(`${experimentId}_${userId}`);
if (!assignment) return null;
const key = `${experimentId}_${assignment.variant}`;
const conversions = this.conversions.get(key) || [];
conversions.push({
userId,
value,
timestamp: Date.now()
});
this.conversions.set(key, conversions);
const experiment = this.experiments.get(experimentId);
experiment.results[assignment.variant] += value;
return assignment.variant;
}
// 获取实验结果
getResults(experimentId) {
const experiment = this.experiments.get(experimentId);
if (!experiment) return null;
const controlConversions = this.conversions.get(`${experimentId}_control`) || [];
const treatmentConversions = this.conversions.get(`${experimentId}_treatment`) || [];
const controlRate = experiment.samples.control > 0
? experiment.results.control / experiment.samples.control
: 0;
const treatmentRate = experiment.samples.treatment > 0
? experiment.results.treatment / experiment.samples.treatment
: 0;
// 计算统计显著性
const significance = this.calculateSignificance(
controlConversions.length,
experiment.samples.control,
treatmentConversions.length,
experiment.samples.treatment
);
// 计算置信区间
const confidenceInterval = this.calculateConfidenceInterval(
treatmentRate - controlRate,
experiment.samples.treatment + experiment.samples.control
);
return {
experimentId,
status: experiment.status,
samples: experiment.samples,
rates: {
control: controlRate,
treatment: treatmentRate
},
lift: controlRate > 0 ? (treatmentRate - controlRate) / controlRate : 0,
confidence: significance,
confidenceInterval,
isSignificant: significance >= experiment.confidence,
recommendation: this.getRecommendation(significance, confidenceInterval, experiment)
};
}
// 计算统计显著性(Z-test)
calculateSignificance(controlConversions, controlSamples, treatmentConversions, treatmentSamples) {
if (controlSamples === 0 || treatmentSamples === 0) return 0;
const controlRate = controlConversions / controlSamples;
const treatmentRate = treatmentConversions / treatmentSamples;
// 合并比例
const pooledRate = (controlConversions + treatmentConversions) /
(controlSamples + treatmentSamples);
// 标准误差
const se = Math.sqrt(pooledRate * (1 - pooledRate) *
(1/controlSamples + 1/treatmentSamples));
if (se === 0) return 0;
// Z-score
const z = Math.abs(treatmentRate - controlRate) / se;
// 转换为置信水平
return this.zToConfidence(z);
}
zToConfidence(z) {
// 使用近似公式
// Z = 1.96 -> 95% confidence
// Z = 2.576 -> 99% confidence
if (z >= 2.576) return 0.99;
if (z >= 2.326) return 0.98;
if (z >= 1.96) return 0.95;
if (z >= 1.645) return 0.90;
return z / 3; // 线性近似
}
// 计算置信区间
calculateConfidenceInterval(diff, totalSamples, confidence = 0.95) {
const se = Math.sqrt(
(diff * (1 - diff)) / totalSamples
);
const zScore = confidence === 0.95 ? 1.96 : 2.576;
return {
lower: diff - zScore * se,
upper: diff + zScore * se
};
}
// 获取推荐决策
getRecommendation(significance, confidenceInterval, experiment) {
if (significance < experiment.confidence) {
return {
action: 'continue',
reason: 'Experiment not yet statistically significant'
};
}
const lift = experiment.results.treatment / experiment.samples.treatment -
experiment.results.control / experiment.samples.control;
if (confidenceInterval.lower > 0) {
return {
action: 'ship_treatment',
reason: `Treatment is ${(lift * 100).toFixed(2)}% better with ${(significance * 100).toFixed(1)}% confidence`
};
} else if (confidenceInterval.upper < 0) {
return {
action: 'ship_control',
reason: `Control is performing better (not expected)`
};
} else {
return {
action: ' inconclusive',
reason: 'Results are not conclusive despite statistical significance'
};
}
}
// 哈希函数
hash(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
return Math.abs(hash);
}
}在 Onboarding 优化过程中,以下几个场景是最值得进行 A/B 测试的:
测试场景 | 变量 | 控制组 | 实验组 | 预期影响 |
|---|---|---|---|---|
引导流程长度 | 步骤数量 | 7 步完整引导 | 3 步简化引导 | 简化版完成率更高,但后续留存可能更低 |
AI 演示时机 | 首次展示 AI 的时间点 | 第 3 步 | 第 1 步 | 早期展示可能提升早期激活率 |
引导方式 | 交互模式 | Tooltips | 交互式教程 | 交互式教程可能提升任务完成率 |
进度条样式 | 视觉呈现 | 百分比 | 步骤图标 | 步骤图标可能减少用户焦虑 |
完成奖励 | 激励机制 | 无奖励 | 徽章/证书 | 奖励可能提升完成率但降低内在动机 |

在设计 AI IDE 的 Onboarding 流程之前,我们需要深入理解目标用户和使用场景。AI IDE 的用户大致可以分为以下几类:
用户类型 | 特征 | 核心需求 | Onboarding 重点 |
|---|---|---|---|
资深开发者 | 10+ 年经验,熟悉多种 IDE | 效率提升,不被束缚 | 快速上手,突出 AI 差异化能力 |
中级开发者 | 3-5 年经验,主用一两种 IDE | 学习曲线平缓 | 渐进式功能展示,与现有习惯衔接 |
初学者 | 编程经验 < 1 年 | 易于理解,不感到 overwhelmed | 强化教程,编程概念解释 |
转行者 | 从其他行业转入 | 职业发展支持 | 编程基础,职业路径指导 |
AI 爱好者 | 对 AI 有强烈兴趣 | 探索 AI 能力 | AI 优先策略 |
AI 怀疑者 | 对 AI 持保留态度 | 证明 AI 价值 | 小步验证,透明过程 |
以下是一个完整的 AI IDE Onboarding 系统的实现示例:
// AI IDE Onboarding 主控制器
class AIIDEOnboarding {
constructor(options = {}) {
this.userId = options.userId;
this.userProfile = options.userProfile || {};
this.preferences = options.preferences || {};
// 子系统初始化
this.tutorialEngine = new InteractiveTutorialEngine();
this.tooltipSystem = new TooltipSystem();
this.aiDemoEngine = new AIDemoEngine();
this.tracker = new ActivationTracker();
this.abTester = new OnboardingABTester();
// 状态管理
this.currentStep = null;
this.completedSteps = new Set();
this.userTrustLevel = 1;
// 初始化
this.initializeComponents();
}
initializeComponents() {
// 注册交互式教程
this.registerTutorials();
// 注册 Tooltips
this.registerTooltips();
// 注册 AI 演示
this.registerAIDemos();
}
// 注册教程
registerTutorials() {
// 欢迎教程
this.tutorialEngine.registerTutorial({
id: 'welcome',
title: '欢迎使用 AI IDE',
category: 'onboarding',
steps: [
{
title: '了解工作区',
instruction: '这是您的主要编辑区域,支持多标签页和分屏。',
targetSelector: '.editor-workspace',
expectedAction: { type: 'observe', duration: 2000 }
},
{
title: '认识 AI 助手面板',
instruction: 'AI 助手在这里为您提供代码建议和解释。',
targetSelector: '.ai-assistant-panel',
expectedAction: { type: 'click' }
},
{
title: '了解文件资源管理器',
instruction: '浏览和管理您的项目文件。',
targetSelector: '.file-explorer',
expectedAction: { type: 'observe', duration: 1000 }
}
]
});
// 第一个项目教程
this.tutorialEngine.registerTutorial({
id: 'first_project',
title: '创建您的第一个项目',
category: 'onboarding',
steps: [
{
title: '点击新建项目',
instruction: '点击"新建项目"按钮开始创建项目。',
targetSelector: '.new-project-btn',
expectedAction: { type: 'click' }
},
{
title: '选择项目模板',
instruction: '选择一个适合您的项目模板。',
targetSelector: '.project-template-list',
expectedAction: { type: 'select', value: 'javascript' }
},
{
title: '命名您的项目',
instruction: '输入项目名称。',
targetSelector: '.project-name-input',
expectedAction: { type: 'input', value: 'my-first-ai-project' }
},
{
title: '创建项目',
instruction: '点击"创建"按钮完成项目创建。',
targetSelector: '.create-project-btn',
expectedAction: { type: 'click' }
}
]
});
// AI 协作教程
this.tutorialEngine.registerTutorial({
id: 'ai_collaboration',
title: '与 AI 协作编程',
category: 'ai_usage',
steps: [
{
title: '打开 AI 助手',
instruction: '按下 Ctrl+Shift+A 打开 AI 助手面板。',
targetSelector: '.ai-assistant-panel',
expectedAction: { type: 'shortcut', value: 'Ctrl+Shift+A' }
},
{
title: '提出第一个问题',
instruction: '向 AI 询问如何实现某个功能。',
targetSelector: '.ai-input-field',
expectedAction: { type: 'input', value: '如何实现数组去重?' }
},
{
title: '查看 AI 建议',
instruction: '查看 AI 给出的代码建议。',
targetSelector: '.ai-suggestion-panel',
expectedAction: { type: 'observe', duration: 3000 }
},
{
title: '接受建议',
instruction: '点击"接受"将代码插入编辑器。',
targetSelector: '.accept-suggestion-btn',
expectedAction: { type: 'click' }
}
]
});
}
// 注册 Tooltips
registerTooltips() {
// 编辑器 Tooltips
this.tooltipSystem.registerTooltip(
'editor-save-btn',
'保存当前文件<br><kbd>Ctrl+S</kbd>',
{ position: 'bottom', trigger: 'hover', timeout: 3000 }
);
this.tooltipSystem.registerTooltip(
'ai-suggestion-btn',
'获取 AI 代码建议<br><kbd>Tab</kbd> 接受建议',
{ position: 'left', trigger: 'hover', timeout: 5000 }
);
this.tooltipSystem.registerTooltip(
'debug-btn',
'启动调试模式<br>设置断点来逐步执行代码',
{ position: 'top', trigger: 'click', overlay: true }
);
}
// 注册 AI 演示
registerAIDemos() {
// 代码补全演示
this.aiDemoEngine.registerDemo({
id: 'code_completion_demo',
title: '智能代码补全',
category: 'ai_capability',
minTrustLevel: 1,
maxTrustLevel: 4,
execute: async (mode) => {
const scenario = {
input: 'function calculateSum(arr) {',
expectedOutput: 'function calculateSum(arr) {\n return arr.reduce((a, b) => a + b, 0);\n}',
context: 'JavaScript 函数,用于计算数组元素之和'
};
// 模拟 AI 生成过程
await this.simulateAIGeneration(1000);
return {
success: true,
output: scenario.expectedOutput,
confidence: 0.95,
mode
};
}
});
// 代码生成演示
this.aiDemoEngine.registerDemo({
id: 'code_generation_demo',
title: '自然语言转代码',
category: 'ai_capability',
minTrustLevel: 2,
maxTrustLevel: 4,
execute: async (mode) => {
const scenario = {
input: '创建一个计时器组件,每秒更新一次显示',
expectedOutput: 'class Timer extends React.Component {\n constructor(props) {\n super(props);\n this.state = { seconds: 0 };\n }\n \n componentDidMount() {\n this.interval = setInterval(() => {\n this.setState(prev => ({ seconds: prev.seconds + 1 }));\n }, 1000);\n }\n \n componentWillUnmount() {\n clearInterval(this.interval);\n }\n \n render() {\n return <div>{this.state.seconds}秒</div>;\n }\n}',
context: 'React 计时器组件'
};
await this.simulateAIGeneration(2000);
return {
success: true,
output: scenario.expectedOutput,
confidence: 0.88,
mode
};
}
});
// 代码解释演示
this.aiDemoEngine.registerDemo({
id: 'code_explanation_demo',
title: '代码智能解释',
category: 'ai_capability',
minTrustLevel: 3,
maxTrustLevel: 4,
execute: async (mode) => {
const scenario = {
input: 'const debounce = (fn, delay) => {\n let timeoutId;\n return (...args) => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => fn(...args), delay);\n };\n};',
explanation: '这是一个防抖函数实现。防抖用于限制函数的执行频率,常用于搜索输入等场景。当用户快速连续输入时,只有最后一次输入会在延迟后触发函数执行。'
};
await this.simulateAIGeneration(1500);
return {
success: true,
explanation: scenario.explanation,
mode
};
}
});
}
// 模拟 AI 生成过程
simulateAIGeneration(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 启动 Onboarding
async start() {
// 记录开始事件
this.tracker.trackEvent(this.userId, {
type: 'onboarding_started',
userProfile: this.userProfile
});
// 根据用户类型选择初始教程
const initialTutorial = this.selectInitialTutorial();
// 开始教程
const state = await this.tutorialEngine.startTutorial(initialTutorial);
return state;
}
// 选择初始教程
selectInitialTutorial() {
const { experience, aiFamiliarity } = this.userProfile;
// 根据用户类型选择
if (experience === 'none') {
return 'programming_basics'; // 编程基础教程
}
if (aiFamiliarity === 'none') {
return 'ai_trust_building'; // AI 信任建立教程
}
return 'welcome'; // 默认欢迎教程
}
// 处理用户操作
async handleUserAction(action) {
const result = await this.tutorialEngine.handleUserAction(action);
if (result) {
// 记录步骤完成
this.tracker.trackOnboardingStep(
this.userId,
result.step?.title || 'unknown',
result.duration || 0
);
// 如果是 AI 相关操作,更新信任度
if (action.type === 'accept_ai_suggestion') {
this.userTrustLevel = Math.min(4, this.userTrustLevel + 0.1);
}
}
return result;
}
// 完成 Onboarding
async complete() {
this.tracker.trackEvent(this.userId, {
type: 'onboarding_completed',
duration: Date.now() - this.startTime
});
this.tracker.trackActivation(this.userId, {
method: 'onboarding_completed',
trustLevel: this.userTrustLevel
});
return {
success: true,
completedSteps: Array.from(this.completedSteps),
totalDuration: Date.now() - this.startTime
};
}
// 获取当前状态
getState() {
return {
currentStep: this.tutorialEngine.getTutorialState(),
completedSteps: Array.from(this.completedSteps),
trustLevel: this.userTrustLevel,
recommendedDemo: this.aiDemoEngine.getAppropriateDemo(this.userId)
};
}
}为了更好地理解整个 Onboarding 流程,我们使用 Mermaid 图表来展示用户旅程和系统架构:


AI IDE 通常面向全球用户,因此 Onboarding 系统必须支持多语言和本地化。以下是国际化 Onboarding 的关键设计要点:
// 国际化 Onboarding 系统
class I18nOnboarding {
constructor(defaultLocale = 'en') {
this.locale = defaultLocale;
this.translations = new Map();
this.fallbackTranslations = new Map();
}
// 加载翻译文件
loadTranslations(locale, translations) {
this.translations.set(locale, translations);
}
// 设置回退翻译
setFallbackTranslations(translations) {
this.fallbackTranslations = translations;
}
// 获取翻译
t(key, params = {}) {
const translations = this.translations.get(this.locale) || this.fallbackTranslations;
let text = translations[key] || this.fallbackTranslations[key] || key;
// 替换参数
for (const [param, value] of Object.entries(params)) {
text = text.replace(`{${param}}`, value);
}
return text;
}
// 获取当前区域设置的 Onboarding 内容
getLocalizedContent(contentId) {
const keys = {
welcome_title: `onboarding.${contentId}.welcome_title`,
welcome_description: `onboarding.${contentId}.welcome_description`,
step_title: `onboarding.${contentId}.step_title`,
step_instruction: `onboarding.${contentId}.step_instruction`,
success_message: `onboarding.${contentId}.success_message`
};
return Object.fromEntries(
Object.entries(keys).map(([k, v]) => [k, this.t(v)])
);
}
// 检测用户区域设置
detectLocale() {
// 优先使用浏览器语言设置
const browserLocale = navigator.language || navigator.userLanguage;
// 检查是否支持该语言
if (this.translations.has(browserLocale)) {
return browserLocale;
}
// 尝试主要语言部分(如 en-US -> en)
const mainLocale = browserLocale.split('-')[0];
if (this.translations.has(mainLocale)) {
return mainLocale;
}
// 回退到默认语言
return this.defaultLocale;
}
}Onboarding 系统的性能直接影响用户体验。以下是一些关键的优化策略:
优化点 | 策略 | 预期效果 |
|---|---|---|
首屏加载 | 延迟加载非关键教程 | 首次加载时间减少 60% |
图片资源 | 使用 WebP 格式,CDN 分发 | 资源大小减少 30% |
动画性能 | 使用 CSS transform | 帧率提升至 60fps |
数据预取 | 预测用户下一步 | 感知响应时间减少 50% |
代码分割 | 按模块动态加载 | 初始包体积减少 40% |
// Onboarding 性能优化管理器
class OnboardingPerformanceOptimizer {
constructor() {
this.resourceHints = new Map();
this.loadedModules = new Set();
this.prefetchQueue = [];
}
// 预取下一个教程资源
prefetchNextTutorial(currentStep) {
const nextStep = this.predictNextStep(currentStep);
if (!nextStep) return;
const resources = this.getTutorialResources(nextStep);
for (const resource of resources) {
if (resource.type === 'image') {
this.prefetchImage(resource.url);
} else if (resource.type === 'video') {
this.prefetchVideo(resource.url);
} else if (resource.type === 'module') {
this.prefetchModule(resource.url);
}
}
}
// 预取图片
prefetchImage(url) {
const link = document.createElement('link');
link.rel = 'prefetch';
link.as = 'image';
link.href = url;
document.head.appendChild(link);
}
// 预取视频
prefetchVideo(url) {
const link = document.createElement('link');
link.rel = 'prefetch';
link.as = 'video';
link.href = url;
document.head.appendChild(link);
}
// 动态导入模块
async prefetchModule(modulePath) {
if (this.loadedModules.has(modulePath)) return;
try {
await import(/* webpackPrefetch: true */ modulePath);
this.loadedModules.add(modulePath);
} catch (e) {
console.warn(`Failed to prefetch module: ${modulePath}`, e);
}
}
// 预测用户下一步
predictNextStep(currentStep) {
// 简单的基于路径的预测
const stepGraph = {
'welcome': ['first_project'],
'first_project': ['ai_collaboration'],
'ai_collaboration': ['debugging_basics'],
'debugging_basics': ['version_control']
};
return stepGraph[currentStep]?.[0];
}
// 获取教程资源列表
getTutorialResources(stepId) {
const resourceMap = {
'welcome': [
{ type: 'image', url: '/images/welcome-editor.webp' },
{ type: 'module', url: './tutorials/welcome.js' }
],
'first_project': [
{ type: 'image', url: '/images/project-templates.webp' },
{ type: 'video', url: '/videos/create-project.webm' },
{ type: 'module', url: './tutorials/first-project.js' }
],
'ai_collaboration': [
{ type: 'image', url: '/images/ai-panel.webp' },
{ type: 'module', url: './tutorials/ai-collaboration.js' }
]
};
return resourceMap[stepId] || [];
}
// 测量性能指标
measurePerformance() {
if (typeof PerformanceObserver === 'undefined') {
return null;
}
const metrics = {
on boardingLoadTime: 0,
firstStepRenderTime: 0,
resourceLoadTimes: {}
};
// 使用 Performance API 获取关键指标
const paintEntries = performance.getEntriesByType('paint');
const navigationEntry = performance.getEntriesByType('navigation')[0];
if (navigationEntry) {
metrics.onboardingLoadTime = navigationEntry.loadEventEnd - navigationEntry.startTime;
}
return metrics;
}
}优秀的 Onboarding 系统应该对所有用户都是可访问的,包括使用辅助技术的用户。无障碍设计不仅是合规要求,更能提升所有用户的体验。
无障碍特性 | 实现方式 | 用户收益 |
|---|---|---|
键盘导航 | 所有交互元素可使用 Tab/Enter 操作 | 不用鼠标的用户 |
屏幕阅读器支持 | ARIA 标签和描述 | 视障用户 |
高对比度模式 | 支持系统级高对比度设置 | 低视力用户 |
字幕支持 | 视频教程提供字幕 | 听障用户 / 静音环境 |
可调节文本大小 | 支持 200% 文本缩放 | 老花眼用户 |
操作超时延长 | 提供更多时间完成操作 | 动作障碍用户 |
// 无障碍 Onboarding 支持
class AccessibleOnboarding {
constructor() {
this.announceElement = this.createAnnounceElement();
this.reduceMotion = this.checkReduceMotionPreference();
}
// 创建 ARIA 实时区域用于屏幕阅读器通知
createAnnounceElement() {
const element = document.createElement('div');
element.id = 'onboarding-announcer';
element.setAttribute('aria-live', 'polite');
element.setAttribute('aria-atomic', 'true');
element.className = 'sr-only'; // screen reader only
element.style.cssText = `
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
`;
document.body.appendChild(element);
return element;
}
// 通知屏幕阅读器
announce(message, priority = 'polite') {
this.announceElement.setAttribute('aria-live', priority);
this.announceElement.textContent = message;
// 清空以便下次通知
setTimeout(() => {
this.announceElement.textContent = '';
}, 1000);
}
// 检查用户是否偏好减少动画
checkReduceMotionPreference() {
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
}
// 获取适合用户的动画设置
getAnimationPreference() {
if (this.reduceMotion) {
return {
duration: 0,
easing: 'linear',
shouldAnimate: false
};
}
// 检查系统级动画设置
const prefersReducedMotion = window.matchMedia(
'(prefers-reduced-motion: reduce)'
).matches;
return {
duration: prefersReducedMotion ? 0 : 300,
easing: prefersReducedMotion ? 'linear' : 'ease-out',
shouldAnimate: !prefersReducedMotion
};
}
// 为教程步骤生成 ARIA 描述
generateStepDescription(step) {
return `Step ${step.order + 1} of ${step.totalSteps}: ${step.title}. ${step.instruction}`;
}
// 键盘导航处理
handleKeyboardNavigation(event, currentStep, steps) {
const { key } = event;
switch (key) {
case 'Enter':
case ' ':
// 确认/继续
return { action: 'confirm' };
case 'Escape':
// 退出或返回
return { action: 'escape' };
case 'ArrowDown':
case 'ArrowRight':
// 下一个元素
return { action: 'next' };
case 'ArrowUp':
case 'ArrowLeft':
// 上一个元素
return { action: 'previous' };
case 'Tab':
// 如果是 Shift+Tab,向上导航
if (event.shiftKey) {
return { action: 'previous' };
}
return { action: 'next' };
default:
return null;
}
}
// 确保焦点管理
trapFocus(containerElement) {
const focusableElements = containerElement.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
const handleTab = (event) => {
if (event.key !== 'Tab') return;
if (event.shiftKey) {
if (document.activeElement === firstElement) {
event.preventDefault();
lastElement.focus();
}
} else {
if (document.activeElement === lastElement) {
event.preventDefault();
firstElement.focus();
}
}
};
containerElement.addEventListener('keydown', handleTab);
return () => {
containerElement.removeEventListener('keydown', handleTab);
};
}
}本文系统性地探讨了 AI IDE Onboarding 设计的完整方法论:
AI IDE 的 Onboarding 设计正在向以下方向发展:
趋势 | 描述 | 影响 |
|---|---|---|
智能化适配 | AI 驱动的个性化 Onboarding | 更精准的用户激活 |
情境感知 | 基于用户上下文动态调整引导 | 更高的相关性 |
社交化学习 | 引入同伴学习和导师指导 | 提升完成率和满意度 |
持续学习 | Onboarding 向持续的产品内指导延伸 | 长期用户成长支持 |
跨平台一致 | 多设备间的 Onboarding 体验同步 | 无缝用户体验 |
成功 Onboarding 系统的关键因素可以用以下公式概括:
其中每一个因素都需要产品、运营、技术团队的紧密协作。作为产品设计者,我们需要始终铭记:
Onboarding 不是一次性的流程,而是用户与产品建立长期关系的起点。
参考链接:
附录(Appendix):
阶段 | 检查项 | 状态 |
|---|---|---|
价值感知 | 产品价值主张清晰传达 | □ |
价值感知 | 目标用户正确识别 | □ |
核心能力 | 核心任务流程顺畅 | □ |
核心能力 | 关键功能可发现 | □ |
信任建立 | AI 能力演示有效 | □ |
信任建立 | 用户信任逐步提升 | □ |
数据监控 | 关键指标已埋点 | □ |
数据监控 | 异常监控已配置 | □ |
持续优化 | A/B 测试机制就绪 | □ |
持续优化 | 用户反馈收集机制 | □ |
指标 | 定义 | 计算公式 |
|---|---|---|
CTR | 点击通过率 | 点击数 / 展示数 |
完成率 | 流程完成比例 | 完成数 / 开始数 |
转化率 | 目标达成比例 | 达成目标用户数 / 总用户数 |
跳出率 | 中途放弃比例 | 放弃数 / 开始数 |
停留时间 | 用户在流程中的时间 | T(完成) - T(开始) |
关键词: Onboarding, 用户引导, 用户激活, AI IDE, 用户体验, 渐进式引导, 交互式教程, A/B测试, 信任模型, 数据驱动设计
