AI编程助手使用指南

🤖 AI编程助手使用指南

系列文章导航

AI编程助手正在革命性地改变软件开发方式,通过智能代码补全、自动生成函数、解释代码逻辑等功能,显著提升开发效率和代码质量。本文将深入介绍主流AI编程助手的使用方法和最佳实践。

📊 AI编程助手对比表

工具 官方地址 核心优势 支持IDE 定价模式 推荐场景
GitHub Copilot copilot.github.com 生态完善、准确率高 VS Code、JetBrains、Vim $10/月 专业开发
Cursor cursor.sh AI原生IDE、对话编程 内置IDE $20/月 全栈开发
Codeium codeium.com 免费、多语言支持 40+ IDEs 免费/企业版 个人开发
Continue continue.dev 开源、可定制 VS Code、JetBrains 免费 定制需求
Tabnine tabnine.com 本地运行、隐私保护 多种IDE $12/月 企业安全

🚀 GitHub Copilot 深度使用指南

🔧 安装和配置

1. VS Code 安装

1
2
3
4
5
6
# 方法1:通过VS Code扩展市场
# 搜索 "GitHub Copilot" 并安装

# 方法2:命令行安装
code --install-extension GitHub.copilot
code --install-extension GitHub.copilot-chat

2. JetBrains IDE 安装

1
2
3
# IntelliJ IDEA / PyCharm / WebStorm
# File -> Settings -> Plugins -> Marketplace
# 搜索 "GitHub Copilot" 并安装

3. 账户配置

1
2
3
4
# 登录GitHub账户
# 在IDE中按 Ctrl+Shift+P (VS Code)
# 输入 "GitHub Copilot: Sign In"
# 按照提示完成OAuth认证

💡 核心功能详解

1. 智能代码补全

Python示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 输入注释,Copilot自动生成代码
# 计算斐波那契数列的第n项
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)

# 创建一个简单的REST API
from flask import Flask, jsonify, request

app = Flask(__name__)

@app.route('/api/users', methods=['GET'])
def get_users():
# Copilot会自动补全API逻辑
users = [
{'id': 1, 'name': 'Alice', 'email': '[email protected]'},
{'id': 2, 'name': 'Bob', 'email': '[email protected]'}
]
return jsonify(users)

@app.route('/api/users', methods=['POST'])
def create_user():
data = request.get_json()
# 验证输入数据
if not data or 'name' not in data or 'email' not in data:
return jsonify({'error': 'Missing required fields'}), 400

# 创建新用户逻辑
new_user = {
'id': len(users) + 1,
'name': data['name'],
'email': data['email']
}
return jsonify(new_user), 201

JavaScript/React示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 创建一个用户管理组件
import React, { useState, useEffect } from 'react';
import axios from 'axios';

const UserManagement = () => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

// 获取用户列表
useEffect(() => {
const fetchUsers = async () => {
try {
setLoading(true);
const response = await axios.get('/api/users');
setUsers(response.data);
} catch (err) {
setError('Failed to fetch users');
} finally {
setLoading(false);
}
};

fetchUsers();
}, []);

// 删除用户
const handleDeleteUser = async (userId) => {
try {
await axios.delete(`/api/users/${userId}`);
setUsers(users.filter(user => user.id !== userId));
} catch (err) {
setError('Failed to delete user');
}
};

if (loading) return <div className="loading">Loading...</div>;
if (error) return <div className="error">{error}</div>;

return (
<div className="user-management">
<h2>User Management</h2>
<div className="user-list">
{users.map(user => (
<div key={user.id} className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
<button
onClick={() => handleDeleteUser(user.id)}
className="delete-btn"
>
Delete
</button>
</div>
))}
</div>
</div>
);
};

export default UserManagement;

2. Copilot Chat 对话编程

使用技巧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 在VS Code中按 Ctrl+Shift+I 打开Copilot Chat

# 示例对话:
用户: "帮我写一个Python函数,用于验证邮箱地址格式"

Copilot:
import re

def validate_email(email):
"""
验证邮箱地址格式是否正确

Args:
email (str): 要验证的邮箱地址

Returns:
bool: 如果邮箱格式正确返回True,否则返回False
"""
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None

# 测试函数
if __name__ == "__main__":
test_emails = [
"[email protected]",
"invalid.email",
"[email protected]",
"@invalid.com"
]

for email in test_emails:
result = validate_email(email)
print(f"{email}: {'Valid' if result else 'Invalid'}")

3. 代码解释和重构

代码解释示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 选中以下复杂代码,右键选择"Copilot: Explain This"
def quick_sort(arr, low, high):
if low < high:
pi = partition(arr, low, high)
quick_sort(arr, low, pi - 1)
quick_sort(arr, pi + 1, high)

def partition(arr, low, high):
pivot = arr[high]
i = low - 1
for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1

# Copilot会解释:
# 这是快速排序算法的实现。quick_sort函数递归地对数组进行排序,
# partition函数选择最后一个元素作为基准,将小于等于基准的元素
# 放在左边,大于基准的元素放在右边,并返回基准的最终位置。

⚙️ 高级配置和优化

1. 自定义设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// VS Code settings.json
{
"github.copilot.enable": {
"*": true,
"yaml": false,
"plaintext": false
},
"github.copilot.advanced": {
"secret_key": "your-secret-key",
"length": 500,
"temperature": 0.1,
"top_p": 1,
"stop": ["\n\n"]
},
"github.copilot.chat.localeOverride": "zh-CN",
"github.copilot.chat.welcomeMessage": "never"
}

2. 快捷键配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// keybindings.json
[
{
"key": "ctrl+shift+a",
"command": "github.copilot.generate",
"when": "editorTextFocus"
},
{
"key": "ctrl+shift+c",
"command": "workbench.panel.chat.view.copilot.focus",
"when": "!chatInputHasFocus"
},
{
"key": "alt+c",
"command": "github.copilot.acceptCursorPanelSuggestion",
"when": "copilotSuggestionVisible"
}
]

🎯 Cursor AI原生IDE使用指南

🔧 安装和初始配置

1. 下载安装

1
2
3
4
5
6
7
8
9
10
11
# Windows
# 访问 https://cursor.sh 下载安装包
# 运行 cursor-setup.exe

# macOS
brew install --cask cursor

# Linux
wget https://download.cursor.sh/linux/appImage/x64
chmod +x cursor-*.AppImage
./cursor-*.AppImage

2. 初始设置

1
2
3
4
# 首次启动时配置
# 1. 选择AI模型(GPT-4、Claude等)
# 2. 导入VS Code设置和扩展
# 3. 配置API密钥

💡 核心功能详解

1. AI对话编程

自然语言编程示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# 在Cursor中按 Ctrl+K 打开AI对话

用户: "创建一个React组件,显示天气信息,包含温度、湿度、风速"

# Cursor会生成:
import React, { useState, useEffect } from 'react';
import './WeatherWidget.css';

interface WeatherData {
temperature: number;
humidity: number;
windSpeed: number;
description: string;
location: string;
}

const WeatherWidget: React.FC = () => {
const [weather, setWeather] = useState<WeatherData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
const fetchWeather = async () => {
try {
setLoading(true);
// 模拟API调用
const response = await fetch('/api/weather');
if (!response.ok) {
throw new Error('Failed to fetch weather data');
}
const data = await response.json();
setWeather(data);
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
} finally {
setLoading(false);
}
};

fetchWeather();
// 每5分钟更新一次
const interval = setInterval(fetchWeather, 5 * 60 * 1000);

return () => clearInterval(interval);
}, []);

if (loading) {
return (
<div className="weather-widget loading">
<div className="spinner"></div>
<p>Loading weather data...</p>
</div>
);
}

if (error) {
return (
<div className="weather-widget error">
<p>Error: {error}</p>
<button onClick={() => window.location.reload()}>
Retry
</button>
</div>
);
}

if (!weather) {
return <div className="weather-widget">No weather data available</div>;
}

return (
<div className="weather-widget">
<div className="weather-header">
<h2>{weather.location}</h2>
<p className="description">{weather.description}</p>
</div>

<div className="weather-metrics">
<div className="metric">
<div className="metric-icon">🌡️</div>
<div className="metric-value">{weather.temperature}°C</div>
<div className="metric-label">Temperature</div>
</div>

<div className="metric">
<div className="metric-icon">💧</div>
<div className="metric-value">{weather.humidity}%</div>
<div className="metric-label">Humidity</div>
</div>

<div className="metric">
<div className="metric-icon">💨</div>
<div className="metric-value">{weather.windSpeed} km/h</div>
<div className="metric-label">Wind Speed</div>
</div>
</div>
</div>
);
};

export default WeatherWidget;

2. 代码库理解和重构

整个项目分析示例:

1
2
3
4
5
6
7
8
9
# 使用 Ctrl+Shift+I 打开项目分析

用户: "分析这个React项目的结构,找出可以优化的地方"

# Cursor会分析整个代码库并提供建议:

## 项目结构分析

### 当前结构:

src/
├── components/
│ ├── Header.jsx
│ ├── Footer.jsx
│ └── UserList.jsx
├── pages/
│ ├── Home.jsx
│ └── About.jsx
├── utils/
│ └── api.js
└── App.jsx

1
2
3
4
5
6
7
8

### 优化建议:

1. **类型安全**:转换为TypeScript
2. **状态管理**:引入Redux Toolkit或Zustand
3. **代码分割**:实现路由级别的懒加载
4. **性能优化**:使用React.memo和useMemo
5. **测试覆盖**:添加单元测试和集成测试

3. 智能重构功能

重构示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// 选中旧代码,使用 Ctrl+Shift+R 进行重构

// 旧代码:
function UserComponent(props) {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(false);

useEffect(() => {
setLoading(true);
fetch('/api/users')
.then(res => res.json())
.then(data => {
setUsers(data);
setLoading(false);
})
.catch(err => {
console.error(err);
setLoading(false);
});
}, []);

return (
<div>
{loading ? <div>Loading...</div> : null}
{users.map(user => (
<div key={user.id}>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
))}
</div>
);
}

// Cursor重构后的代码:
import React, { useState, useEffect, useCallback } from 'react';
import { User } from '../types/User';
import { fetchUsers } from '../services/userService';
import { LoadingSpinner } from './LoadingSpinner';
import { UserCard } from './UserCard';
import { ErrorBoundary } from './ErrorBoundary';

interface UserComponentProps {
onUserSelect?: (user: User) => void;
className?: string;
}

const UserComponent: React.FC<UserComponentProps> = ({
onUserSelect,
className = ''
}) => {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

const loadUsers = useCallback(async () => {
try {
setLoading(true);
setError(null);
const userData = await fetchUsers();
setUsers(userData);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load users');
} finally {
setLoading(false);
}
}, []);

useEffect(() => {
loadUsers();
}, [loadUsers]);

const handleUserClick = useCallback((user: User) => {
onUserSelect?.(user);
}, [onUserSelect]);

if (loading) {
return <LoadingSpinner message="Loading users..." />;
}

if (error) {
return (
<div className="error-container">
<p>Error: {error}</p>
<button onClick={loadUsers}>Retry</button>
</div>
);
}

return (
<ErrorBoundary>
<div className={`user-component ${className}`}>
<div className="user-grid">
{users.map(user => (
<UserCard
key={user.id}
user={user}
onClick={handleUserClick}
/>
))}
</div>
{users.length === 0 && (
<div className="empty-state">
<p>No users found</p>
</div>
)}
</div>
</ErrorBoundary>
);
};

export default React.memo(UserComponent);

⚙️ 高级功能配置

1. 自定义AI模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// cursor-settings.json
{
"ai.model": "gpt-4-turbo",
"ai.temperature": 0.1,
"ai.maxTokens": 2000,
"ai.contextLength": 8000,
"ai.customInstructions": [
"Always use TypeScript for React components",
"Follow clean code principles",
"Include proper error handling",
"Add JSDoc comments for functions"
],
"ai.codeStyle": {
"indentation": "2 spaces",
"quotes": "single",
"semicolons": true,
"trailingCommas": "es5"
}
}

4. 前端组件开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// client/src/components/TaskCard.tsx
// 使用GitHub Copilot生成React组件

import React, { useState } from 'react';
import { Task, TaskStatus, Priority } from '../types/task';
import { formatDistanceToNow } from 'date-fns';
import { zhCN } from 'date-fns/locale';

interface TaskCardProps {
task: Task;
onUpdate: (taskId: string, updates: Partial<Task>) => void;
onDelete: (taskId: string) => void;
}

const priorityColors = {
LOW: 'bg-gray-100 text-gray-800',
MEDIUM: 'bg-blue-100 text-blue-800',
HIGH: 'bg-orange-100 text-orange-800',
URGENT: 'bg-red-100 text-red-800'
};

const statusColors = {
TODO: 'bg-gray-100 text-gray-800',
IN_PROGRESS: 'bg-yellow-100 text-yellow-800',
REVIEW: 'bg-purple-100 text-purple-800',
DONE: 'bg-green-100 text-green-800'
};

export const TaskCard: React.FC<TaskCardProps> = ({ task, onUpdate, onDelete }) => {
const [isEditing, setIsEditing] = useState(false);
const [editedTask, setEditedTask] = useState(task);

const handleSave = () => {
onUpdate(task.id, editedTask);
setIsEditing(false);
};

const handleCancel = () => {
setEditedTask(task);
setIsEditing(false);
};

const handleStatusChange = (status: TaskStatus) => {
onUpdate(task.id, { status });
};

const handlePriorityChange = (priority: Priority) => {
onUpdate(task.id, { priority });
};

return (
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-4 hover:shadow-md transition-shadow">
{/* 任务头部 */}
<div className="flex items-start justify-between mb-3">
<div className="flex-1">
{isEditing ? (
<input
type="text"
value={editedTask.title}
onChange={(e) => setEditedTask({ ...editedTask, title: e.target.value })}
className="w-full text-lg font-semibold border-b border-gray-300 focus:border-blue-500 outline-none"
autoFocus
/>
) : (
<h3 className="text-lg font-semibold text-gray-900 cursor-pointer hover:text-blue-600"
onClick={() => setIsEditing(true)}>
{task.title}
</h3>
)}

{task.description && (
<p className="text-gray-600 mt-1 text-sm">
{isEditing ? (
<textarea
value={editedTask.description || ''}
onChange={(e) => setEditedTask({ ...editedTask, description: e.target.value })}
className="w-full border border-gray-300 rounded p-2 text-sm"
rows={2}
/>
) : (
task.description
)}
</p>
)}
</div>

{/* 操作按钮 */}
<div className="flex items-center space-x-2 ml-4">
{isEditing ? (
<>
<button
onClick={handleSave}
className="text-green-600 hover:text-green-800 text-sm font-medium"
>
保存
</button>
<button
onClick={handleCancel}
className="text-gray-600 hover:text-gray-800 text-sm font-medium"
>
取消
</button>
</>
) : (
<>
<button
onClick={() => setIsEditing(true)}
className="text-blue-600 hover:text-blue-800 text-sm font-medium"
>
编辑
</button>
<button
onClick={() => onDelete(task.id)}
className="text-red-600 hover:text-red-800 text-sm font-medium"
>
删除
</button>
</>
)}
</div>
</div>

{/* 标签和状态 */}
<div className="flex items-center space-x-2 mb-3">
{/* 优先级 */}
<select
value={task.priority}
onChange={(e) => handlePriorityChange(e.target.value as Priority)}
className={`px-2 py-1 rounded-full text-xs font-medium border-0 cursor-pointer ${priorityColors[task.priority]}`}
>
<option value="LOW">低优先级</option>
<option value="MEDIUM">中优先级</option>
<option value="HIGH">高优先级</option>
<option value="URGENT">紧急</option>
</select>

{/* 状态 */}
<select
value={task.status}
onChange={(e) => handleStatusChange(e.target.value as TaskStatus)}
className={`px-2 py-1 rounded-full text-xs font-medium border-0 cursor-pointer ${statusColors[task.status]}`}
>
<option value="TODO">待办</option>
<option value="IN_PROGRESS">进行中</option>
<option value="REVIEW">审核中</option>
<option value="DONE">已完成</option>
</select>

{/* 项目标签 */}
{task.project && (
<span
className="px-2 py-1 rounded-full text-xs font-medium text-white"
style={{ backgroundColor: task.project.color }}
>
{task.project.name}
</span>
)}
</div>

{/* 底部信息 */}
<div className="flex items-center justify-between text-sm text-gray-500">
<div className="flex items-center space-x-4">
{/* 分配给 */}
{task.assignee && (
<div className="flex items-center space-x-1">
{task.assignee.avatar ? (
<img
src={task.assignee.avatar}
alt={task.assignee.name}
className="w-5 h-5 rounded-full"
/>
) : (
<div className="w-5 h-5 rounded-full bg-gray-300 flex items-center justify-center text-xs">
{task.assignee.name.charAt(0).toUpperCase()}
</div>
)}
<span>{task.assignee.name}</span>
</div>
)}

{/* 截止日期 */}
{task.dueDate && (
<div className={`flex items-center space-x-1 ${
new Date(task.dueDate) < new Date() ? 'text-red-500' : ''
}`}>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span>
{formatDistanceToNow(new Date(task.dueDate), {
addSuffix: true,
locale: zhCN
})}
</span>
</div>
)}
</div>

{/* 创建时间 */}
<span>
创建于 {formatDistanceToNow(new Date(task.createdAt), {
addSuffix: true,
locale: zhCN
})}
</span>
</div>
</div>
);
};

5. 自定义Hook开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// client/src/hooks/useTasks.ts
// 使用Cursor生成数据管理Hook

import { useState, useEffect, useCallback } from 'react';
import { Task, TaskStatus, Priority, CreateTaskData, UpdateTaskData } from '../types/task';
import { taskService } from '../services/taskService';
import { useToast } from './useToast';

interface UseTasksOptions {
projectId?: string;
status?: TaskStatus;
priority?: Priority;
assigneeId?: string;
search?: string;
autoRefresh?: boolean;
refreshInterval?: number;
}

interface UseTasksReturn {
tasks: Task[];
loading: boolean;
error: string | null;
pagination: {
page: number;
limit: number;
total: number;
pages: number;
};
stats: {
total: number;
byStatus: Record<TaskStatus, number>;
byPriority: Record<Priority, number>;
};
// 操作方法
createTask: (data: CreateTaskData) => Promise<Task | null>;
updateTask: (id: string, data: UpdateTaskData) => Promise<Task | null>;
deleteTask: (id: string) => Promise<boolean>;
refreshTasks: () => Promise<void>;
loadMore: () => Promise<void>;
setFilters: (filters: Partial<UseTasksOptions>) => void;
}

export const useTasks = (options: UseTasksOptions = {}): UseTasksReturn => {
const [tasks, setTasks] = useState<Task[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [pagination, setPagination] = useState({
page: 1,
limit: 10,
total: 0,
pages: 0
});
const [stats, setStats] = useState({
total: 0,
byStatus: {} as Record<TaskStatus, number>,
byPriority: {} as Record<Priority, number>
});
const [filters, setFilters] = useState(options);

const { showToast } = useToast();

// 加载任务列表
const loadTasks = useCallback(async (page = 1, append = false) => {
try {
setLoading(true);
setError(null);

const response = await taskService.getTasks({
page,
limit: pagination.limit,
...filters
});

if (response.success) {
setTasks(prev => append ? [...prev, ...response.data] : response.data);
setPagination(response.pagination!);
} else {
setError(response.error || '加载任务失败');
}
} catch (err) {
setError('网络错误,请稍后重试');
console.error('Error loading tasks:', err);
} finally {
setLoading(false);
}
}, [filters, pagination.limit]);

// 加载统计信息
const loadStats = useCallback(async () => {
try {
const response = await taskService.getTaskStats({
projectId: filters.projectId
});

if (response.success) {
setStats(response.data);
}
} catch (err) {
console.error('Error loading stats:', err);
}
}, [filters.projectId]);

// 创建任务
const createTask = useCallback(async (data: CreateTaskData): Promise<Task | null> => {
try {
const response = await taskService.createTask(data);

if (response.success) {
setTasks(prev => [response.data, ...prev]);
setPagination(prev => ({ ...prev, total: prev.total + 1 }));
showToast('任务创建成功', 'success');
loadStats(); // 更新统计信息
return response.data;
} else {
showToast(response.error || '创建任务失败', 'error');
return null;
}
} catch (err) {
showToast('网络错误,请稍后重试', 'error');
console.error('Error creating task:', err);
return null;
}
}, [showToast, loadStats]);

// 更新任务
const updateTask = useCallback(async (id: string, data: UpdateTaskData): Promise<Task | null> => {
try {
const response = await taskService.updateTask(id, data);

if (response.success) {
setTasks(prev => prev.map(task =>
task.id === id ? response.data : task
));
showToast('任务更新成功', 'success');
loadStats(); // 更新统计信息
return response.data;
} else {
showToast(response.error || '更新任务失败', 'error');
return null;
}
} catch (err) {
showToast('网络错误,请稍后重试', 'error');
console.error('Error updating task:', err);
return null;
}
}, [showToast, loadStats]);

// 删除任务
const deleteTask = useCallback(async (id: string): Promise<boolean> => {
try {
const response = await taskService.deleteTask(id);

if (response.success) {
setTasks(prev => prev.filter(task => task.id !== id));
setPagination(prev => ({ ...prev, total: prev.total - 1 }));
showToast('任务删除成功', 'success');
loadStats(); // 更新统计信息
return true;
} else {
showToast(response.error || '删除任务失败', 'error');
return false;
}
} catch (err) {
showToast('网络错误,请稍后重试', 'error');
console.error('Error deleting task:', err);
return false;
}
}, [showToast, loadStats]);

// 刷新任务列表
const refreshTasks = useCallback(async () => {
await loadTasks(1, false);
await loadStats();
}, [loadTasks, loadStats]);

// 加载更多
const loadMore = useCallback(async () => {
if (pagination.page < pagination.pages) {
await loadTasks(pagination.page + 1, true);
}
}, [loadTasks, pagination.page, pagination.pages]);

// 设置过滤器
const setFiltersCallback = useCallback((newFilters: Partial<UseTasksOptions>) => {
setFilters(prev => ({ ...prev, ...newFilters }));
}, []);

// 初始加载
useEffect(() => {
loadTasks();
loadStats();
}, [loadTasks, loadStats]);

// 自动刷新
useEffect(() => {
if (options.autoRefresh) {
const interval = setInterval(() => {
refreshTasks();
}, options.refreshInterval || 30000); // 默认30秒

return () => clearInterval(interval);
}
}, [options.autoRefresh, options.refreshInterval, refreshTasks]);

return {
tasks,
loading,
error,
pagination,
stats,
createTask,
updateTask,
deleteTask,
refreshTasks,
loadMore,
setFilters: setFiltersCallback
};
};

📈 AI编程效果评估

1. 开发效率提升

量化指标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
**代码生成速度**:
- 样板代码: 提升 80-90%
- 业务逻辑: 提升 40-60%
- 测试代码: 提升 70-80%
- 文档编写: 提升 60-70%

**错误减少率**:
- 语法错误: 减少 85%
- 类型错误: 减少 70%
- 逻辑错误: 减少 30%
- 最佳实践违反: 减少 60%

**学习曲线**:
- 新技术上手: 缩短 50%
- API使用学习: 缩短 60%
- 代码模式理解: 缩短 40%

实际案例对比

1
2
3
4
5
6
7
8
9
10
11
12
13
// 传统开发方式 (预估时间: 2小时)
// 1. 查阅文档 (30分钟)
// 2. 编写基础结构 (45分钟)
// 3. 实现业务逻辑 (30分钟)
// 4. 调试和优化 (15分钟)

// AI辅助开发 (实际时间: 45分钟)
// 1. AI生成基础结构 (5分钟)
// 2. AI辅助业务逻辑 (20分钟)
// 3. 人工审查和调整 (15分钟)
// 4. 测试和优化 (5分钟)

// 效率提升: 62.5%

2. 代码质量分析

AI生成代码的优势

1
2
3
4
5
**结构规范**: 遵循最佳实践和设计模式
**类型安全**: 完整的TypeScript类型定义
**错误处理**: 全面的异常处理机制
**性能优化**: 合理的算法和数据结构选择
**可维护性**: 清晰的代码组织和注释

需要人工优化的方面

1
2
3
4
5
⚠️ **业务逻辑**: 需要结合具体需求调整
⚠️ **性能调优**: 针对特定场景的优化
⚠️ **安全考虑**: 敏感数据处理和权限控制
⚠️ **用户体验**: 交互细节和边界情况
⚠️ **集成测试**: 端到端的功能验证

🎯 总结与展望

1. 核心收获

技术层面

  • AI编程助手已成为现代开发的标配工具
  • 不同工具有各自的优势场景,组合使用效果最佳
  • AI辅助≠完全自动化,人工审查和优化仍然关键
  • 持续学习和适应新工具是保持竞争力的必要条件

实践层面

  • 建立标准化的AI辅助开发流程
  • 培养良好的提示词(Prompt)编写技能
  • 重视代码安全和质量控制
  • 平衡开发效率与代码可维护性

2. 选择建议总结

🏆 最佳组合推荐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
**企业级开发**:
- 主力: GitHub Copilot (生态完善,质量稳定)
- 辅助: Tabnine (本地运行,保护隐私)
- 场景: 大型项目,团队协作

**个人开发者**:
- 主力: Codeium (免费强大)
- 辅助: Continue (开源可定制)
- 场景: 个人项目,学习实验

**初创团队**:
- 主力: Cursor (AI原生IDE)
- 辅助: Codeium (成本控制)
- 场景: 快速原型,敏捷开发

**学习教育**:
- 主力: GitHub Copilot (学生免费)
- 辅助: Continue (理解原理)
- 场景: 技能提升,概念学习

3. 未来发展趋势

技术演进方向

1
2
3
4
5
🔮 **多模态编程**: 支持语音、图像、视频输入
🔮 **智能重构**: 自动化代码优化和架构调整
🔮 **实时协作**: AI参与的团队编程模式
🔮 **领域专精**: 针对特定行业的专业AI助手
🔮 **端到端开发**: 从需求到部署的全流程AI支持

行业影响预测

1
2
3
4
5
📈 **开发效率**: 预计未来3年提升100-200%
📈 **准入门槛**: 编程学习变得更加容易
📈 **角色转变**: 开发者更专注于创意和架构设计
📈 **质量提升**: AI辅助的代码审查和测试
📈 **成本降低**: 开发和维护成本显著下降

4. 学习路径建议

阶段一:基础入门 (1-2周)

1
2
3
4
1. **选择主力工具**: 根据场景选择一个主要工具
2. **基础功能掌握**: 代码补全、简单生成
3. **提示词技巧**: 学习有效的指令编写
4. **安全意识**: 了解代码审查的重要性

阶段二:进阶应用 (2-4周)

1
2
3
4
1. **多工具组合**: 尝试不同工具的配合使用
2. **复杂项目实践**: 在实际项目中应用AI助手
3. **自定义配置**: 根据需求调整工具设置
4. **团队协作**: 建立团队的AI使用规范

阶段三:专家级应用 (持续)

1
2
3
4
1. **深度定制**: 开发自定义插件和配置
2. **最佳实践**: 总结和分享使用经验
3. **新工具跟踪**: 持续关注行业发展
4. **知识分享**: 帮助团队提升AI使用技能

📚 相关资源

官方文档

学习资源

社区交流


下一篇预告: 《AI开发工具生态系统总结与未来展望》

将深入探讨AI开发工具的整体生态,分析各类工具的协同效应,并预测未来发展方向。
// .cursor/settings.json
{
“ai.projectContext”: {
“framework”: “React + TypeScript”,
“stateManagement”: “Redux Toolkit”,
“styling”: “Tailwind CSS”,
“testing”: “Jest + React Testing Library”,
“buildTool”: “Vite”
},
“ai.excludeFiles”: [
“node_modules/“,
“dist/
“,
.log”,
“.env

],
“ai.includePatterns”: [
“src/**/.{ts,tsx,js,jsx}”,
.md”,
“package.json”
]
}

1
2
3
4
5
6
7
8
9
10
11
12

---

## 🆓 Codeium 免费AI编程助手

### 🔧 安装和配置

#### 1. VS Code 安装
```bash
# 扩展市场搜索 "Codeium" 并安装
# 或使用命令行
code --install-extension Codeium.codeium

2. 账户注册

1
2
3
4
# 1. 访问 https://codeium.com 注册账户
# 2. 在VS Code中按 Ctrl+Shift+P
# 3. 输入 "Codeium: Login"
# 4. 按照提示完成认证

💡 核心功能使用

1. 多语言代码补全

Python数据科学示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix

# 加载和预处理数据
def load_and_preprocess_data(file_path):
"""
加载CSV数据并进行预处理

Args:
file_path (str): CSV文件路径

Returns:
tuple: 处理后的特征和标签
"""
# Codeium会自动补全数据处理逻辑
df = pd.read_csv(file_path)

# 处理缺失值
df = df.dropna()

# 编码分类变量
categorical_columns = df.select_dtypes(include=['object']).columns
df_encoded = pd.get_dummies(df, columns=categorical_columns)

# 分离特征和标签
X = df_encoded.drop('target', axis=1)
y = df_encoded['target']

return X, y

# 训练机器学习模型
def train_model(X, y):
"""
训练随机森林分类器

Args:
X: 特征数据
y: 标签数据

Returns:
tuple: 训练好的模型和测试数据
"""
# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)

# 创建和训练模型
model = RandomForestClassifier(
n_estimators=100,
max_depth=10,
random_state=42,
n_jobs=-1
)

model.fit(X_train, y_train)

return model, X_test, y_test

# 评估模型性能
def evaluate_model(model, X_test, y_test):
"""
评估模型性能并生成报告

Args:
model: 训练好的模型
X_test: 测试特征
y_test: 测试标签
"""
# 预测
y_pred = model.predict(X_test)

# 打印分类报告
print("Classification Report:")
print(classification_report(y_test, y_pred))

# 绘制混淆矩阵
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8, 6))
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.title('Confusion Matrix')
plt.colorbar()
plt.xlabel('Predicted Label')
plt.ylabel('True Label')
plt.show()

# 特征重要性
feature_importance = pd.DataFrame({
'feature': X_test.columns,
'importance': model.feature_importances_
}).sort_values('importance', ascending=False)

plt.figure(figsize=(10, 8))
plt.barh(feature_importance['feature'][:10], feature_importance['importance'][:10])
plt.title('Top 10 Feature Importance')
plt.xlabel('Importance')
plt.tight_layout()
plt.show()

# 主函数
if __name__ == "__main__":
# 加载数据
X, y = load_and_preprocess_data('data.csv')

# 训练模型
model, X_test, y_test = train_model(X, y)

# 评估模型
evaluate_model(model, X_test, y_test)

Go语言Web服务示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
package main

import (
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
"time"

"github.com/gorilla/mux"
"github.com/gorilla/handlers"
)

// User 用户结构体
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Created time.Time `json:"created"`
}

// UserService 用户服务
type UserService struct {
users []User
nextID int
}

// NewUserService 创建新的用户服务
func NewUserService() *UserService {
return &UserService{
users: []User{
{ID: 1, Name: "Alice", Email: "[email protected]", Created: time.Now()},
{ID: 2, Name: "Bob", Email: "[email protected]", Created: time.Now()},
},
nextID: 3,
}
}

// GetAllUsers 获取所有用户
func (us *UserService) GetAllUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")

if err := json.NewEncoder(w).Encode(us.users); err != nil {
http.Error(w, "Failed to encode users", http.StatusInternalServerError)
return
}
}

// GetUser 根据ID获取用户
func (us *UserService) GetUser(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.Atoi(vars["id"])
if err != nil {
http.Error(w, "Invalid user ID", http.StatusBadRequest)
return
}

for _, user := range us.users {
if user.ID == id {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
return
}
}

http.Error(w, "User not found", http.StatusNotFound)
}

// CreateUser 创建新用户
func (us *UserService) CreateUser(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}

// 验证输入
if user.Name == "" || user.Email == "" {
http.Error(w, "Name and email are required", http.StatusBadRequest)
return
}

// 设置ID和创建时间
user.ID = us.nextID
user.Created = time.Now()
us.nextID++

// 添加到用户列表
us.users = append(us.users, user)

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}

// UpdateUser 更新用户信息
func (us *UserService) UpdateUser(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.Atoi(vars["id"])
if err != nil {
http.Error(w, "Invalid user ID", http.StatusBadRequest)
return
}

var updatedUser User
if err := json.NewDecoder(r.Body).Decode(&updatedUser); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}

for i, user := range us.users {
if user.ID == id {
updatedUser.ID = id
updatedUser.Created = user.Created
us.users[i] = updatedUser

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(updatedUser)
return
}
}

http.Error(w, "User not found", http.StatusNotFound)
}

// DeleteUser 删除用户
func (us *UserService) DeleteUser(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.Atoi(vars["id"])
if err != nil {
http.Error(w, "Invalid user ID", http.StatusBadRequest)
return
}

for i, user := range us.users {
if user.ID == id {
us.users = append(us.users[:i], us.users[i+1:]...)
w.WriteHeader(http.StatusNoContent)
return
}
}

http.Error(w, "User not found", http.StatusNotFound)
}

// 中间件:日志记录
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf("%s %s %v", r.Method, r.URL.Path, time.Since(start))
})
}

// 中间件:CORS
func corsMiddleware(next http.Handler) http.Handler {
return handlers.CORS(
handlers.AllowedOrigins([]string{"*"}),
handlers.AllowedMethods([]string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}),
handlers.AllowedHeaders([]string{"Content-Type", "Authorization"}),
)(next)
}

func main() {
userService := NewUserService()

r := mux.NewRouter()

// API路由
api := r.PathPrefix("/api/v1").Subrouter()
api.HandleFunc("/users", userService.GetAllUsers).Methods("GET")
api.HandleFunc("/users/{id}", userService.GetUser).Methods("GET")
api.HandleFunc("/users", userService.CreateUser).Methods("POST")
api.HandleFunc("/users/{id}", userService.UpdateUser).Methods("PUT")
api.HandleFunc("/users/{id}", userService.DeleteUser).Methods("DELETE")

// 健康检查
r.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "healthy"})
}).Methods("GET")

// 应用中间件
r.Use(loggingMiddleware)
r.Use(corsMiddleware)

// 启动服务器
port := ":8080"
fmt.Printf("Server starting on port %s\n", port)
log.Fatal(http.ListenAndServe(port, r))
}

2. 智能聊天功能

使用Codeium Chat:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 在VS Code中按 Ctrl+Shift+P
# 输入 "Codeium: Open Chat"

# 示例对话:
用户: "这段代码有什么问题?如何优化?"

# 选中问题代码
function processData(data) {
var result = [];
for (var i = 0; i < data.length; i++) {
if (data[i].active == true) {
result.push({
id: data[i].id,
name: data[i].name,
status: 'active'
});
}
}
return result;
}

# Codeium会分析并建议:

## 问题分析:
1. 使用 `var` 而不是 `const/let`
2. 使用 `==` 而不是 `===`
3. 可以使用数组方法简化代码
4. 缺少类型检查和错误处理

## 优化建议:

```javascript
// 优化后的代码
function processData(data) {
// 输入验证
if (!Array.isArray(data)) {
throw new Error('Input must be an array');
}

// 使用filter和map链式操作
return data
.filter(item => item?.active === true)
.map(item => ({
id: item.id,
name: item.name,
status: 'active'
}));
}

// 或者使用更现代的语法
const processData = (data) => {
if (!Array.isArray(data)) {
throw new Error('Input must be an array');
}

return data
.filter(({ active }) => active === true)
.map(({ id, name }) => ({ id, name, status: 'active' }));
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

### ⚙️ 配置和自定义

#### 1. 个性化设置
```json
// VS Code settings.json
{
"codeium.enableCodeLens": true,
"codeium.enableSearch": true,
"codeium.enableChat": true,
"codeium.aggressiveMode": false,
"codeium.suggestionMode": "automatic",
"codeium.numSuggestions": 3,
"codeium.maxPromptTokens": 20000,
"codeium.language": "zh-CN"
}

2. 语言特定配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"codeium.languageServer": {
"python": {
"enabled": true,
"suggestions": "enhanced"
},
"javascript": {
"enabled": true,
"suggestions": "standard"
},
"typescript": {
"enabled": true,
"suggestions": "enhanced"
}
}
}

🔧 Continue 开源AI编程助手

🔧 安装和配置

1. VS Code 安装

1
2
3
4
5
6
7
8
# 从扩展市场安装
code --install-extension Continue.continue

# 或从GitHub下载
git clone https://github.com/continuedev/continue.git
cd continue
npm install
npm run build

2. 配置文件设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// ~/.continue/config.json
{
"models": [
{
"title": "GPT-4",
"provider": "openai",
"model": "gpt-4-turbo",
"apiKey": "your-openai-api-key"
},
{
"title": "Claude",
"provider": "anthropic",
"model": "claude-3-sonnet",
"apiKey": "your-anthropic-api-key"
},
{
"title": "Local Ollama",
"provider": "ollama",
"model": "codellama:7b",
"apiBase": "http://localhost:11434"
}
],
"customCommands": [
{
"name": "test",
"prompt": "Write comprehensive unit tests for the following code:\n\n{{{ input }}}\n\nUse Jest and include edge cases.",
"description": "Generate unit tests"
},
{
"name": "optimize",
"prompt": "Optimize the following code for performance and readability:\n\n{{{ input }}}\n\nExplain the optimizations made.",
"description": "Optimize code"
},
{
"name": "document",
"prompt": "Add comprehensive documentation to the following code:\n\n{{{ input }}}\n\nInclude JSDoc comments, parameter descriptions, and usage examples.",
"description": "Add documentation"
}
],
"slashCommands": [
{
"name": "edit",
"description": "Edit code in place"
},
{
"name": "comment",
"description": "Add comments to code"
}
],
"contextProviders": [
{
"name": "diff",
"params": {}
},
{
"name": "terminal",
"params": {}
},
{
"name": "problems",
"params": {}
},
{
"name": "folder",
"params": {
"folders": ["src", "tests"]
}
}
]
}

💡 高级功能使用

1. 自定义命令示例

代码重构命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# 在Continue中输入 /refactor
# 选中需要重构的代码

# 示例:重构React类组件为函数组件
class UserProfile extends React.Component {
constructor(props) {
super(props);
this.state = {
user: null,
loading: true,
error: null
};
}

componentDidMount() {
this.fetchUser();
}

fetchUser = async () => {
try {
const response = await fetch(`/api/users/${this.props.userId}`);
const user = await response.json();
this.setState({ user, loading: false });
} catch (error) {
this.setState({ error: error.message, loading: false });
}
}

render() {
const { user, loading, error } = this.state;

if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!user) return <div>User not found</div>;

return (
<div className="user-profile">
<h2>{user.name}</h2>
<p>{user.email}</p>
<p>Joined: {new Date(user.createdAt).toLocaleDateString()}</p>
</div>
);
}
}

# Continue会重构为:
import React, { useState, useEffect } from 'react';

interface User {
id: string;
name: string;
email: string;
createdAt: string;
}

interface UserProfileProps {
userId: string;
}

const UserProfile: React.FC<UserProfileProps> = ({ userId }) => {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
const fetchUser = async () => {
try {
setLoading(true);
setError(null);
const response = await fetch(`/api/users/${userId}`);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const userData = await response.json();
setUser(userData);
} catch (err) {
setError(err instanceof Error ? err.message : 'An error occurred');
} finally {
setLoading(false);
}
};

if (userId) {
fetchUser();
}
}, [userId]);

if (loading) {
return (
<div className="user-profile loading">
<div className="spinner" />
<span>Loading user profile...</span>
</div>
);
}

if (error) {
return (
<div className="user-profile error">
<h3>Error loading profile</h3>
<p>{error}</p>
<button onClick={() => window.location.reload()}>
Try Again
</button>
</div>
);
}

if (!user) {
return (
<div className="user-profile not-found">
<h3>User not found</h3>
<p>The requested user could not be found.</p>
</div>
);
}

return (
<div className="user-profile">
<div className="user-header">
<h2>{user.name}</h2>
<span className="user-email">{user.email}</span>
</div>
<div className="user-details">
<p className="join-date">
Member since: {new Date(user.createdAt).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</p>
</div>
</div>
);
};

export default UserProfile;

2. 上下文感知编程

项目级别的代码生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# Continue会分析整个项目结构
# 理解现有的代码模式和架构

用户: "为这个React项目添加一个购物车功能"

# Continue分析项目后生成:

// types/cart.ts
export interface CartItem {
id: string;
productId: string;
name: string;
price: number;
quantity: number;
image?: string;
}

export interface Cart {
items: CartItem[];
total: number;
itemCount: number;
}

// hooks/useCart.ts
import { useState, useEffect, useCallback } from 'react';
import { CartItem, Cart } from '../types/cart';

const CART_STORAGE_KEY = 'shopping-cart';

export const useCart = () => {
const [cart, setCart] = useState<Cart>({
items: [],
total: 0,
itemCount: 0
});

// 从localStorage加载购物车
useEffect(() => {
const savedCart = localStorage.getItem(CART_STORAGE_KEY);
if (savedCart) {
try {
const parsedCart = JSON.parse(savedCart);
setCart(parsedCart);
} catch (error) {
console.error('Failed to parse saved cart:', error);
}
}
}, []);

// 保存购物车到localStorage
useEffect(() => {
localStorage.setItem(CART_STORAGE_KEY, JSON.stringify(cart));
}, [cart]);

// 计算总价和商品数量
const updateCartTotals = useCallback((items: CartItem[]) => {
const total = items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
const itemCount = items.reduce((sum, item) => sum + item.quantity, 0);
return { total, itemCount };
}, []);

// 添加商品到购物车
const addToCart = useCallback((product: Omit<CartItem, 'quantity'>) => {
setCart(prevCart => {
const existingItem = prevCart.items.find(item => item.productId === product.productId);

let newItems: CartItem[];
if (existingItem) {
newItems = prevCart.items.map(item =>
item.productId === product.productId
? { ...item, quantity: item.quantity + 1 }
: item
);
} else {
newItems = [...prevCart.items, { ...product, quantity: 1 }];
}

const { total, itemCount } = updateCartTotals(newItems);
return { items: newItems, total, itemCount };
});
}, [updateCartTotals]);

// 更新商品数量
const updateQuantity = useCallback((productId: string, quantity: number) => {
if (quantity <= 0) {
removeFromCart(productId);
return;
}

setCart(prevCart => {
const newItems = prevCart.items.map(item =>
item.productId === productId
? { ...item, quantity }
: item
);

const { total, itemCount } = updateCartTotals(newItems);
return { items: newItems, total, itemCount };
});
}, [updateCartTotals]);

// 从购物车移除商品
const removeFromCart = useCallback((productId: string) => {
setCart(prevCart => {
const newItems = prevCart.items.filter(item => item.productId !== productId);
const { total, itemCount } = updateCartTotals(newItems);
return { items: newItems, total, itemCount };
});
}, [updateCartTotals]);

// 清空购物车
const clearCart = useCallback(() => {
setCart({ items: [], total: 0, itemCount: 0 });
}, []);

return {
cart,
addToCart,
updateQuantity,
removeFromCart,
clearCart
};
};

// components/Cart/CartIcon.tsx
import React from 'react';
import { useCart } from '../../hooks/useCart';
import './CartIcon.css';

interface CartIconProps {
onClick: () => void;
className?: string;
}

const CartIcon: React.FC<CartIconProps> = ({ onClick, className = '' }) => {
const { cart } = useCart();

return (
<button
className={`cart-icon ${className}`}
onClick={onClick}
aria-label={`Shopping cart with ${cart.itemCount} items`}
>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M3 3H5L5.4 5M7 13H17L21 5H5.4M7 13L5.4 5M7 13L4.7 15.3C4.3 15.7 4.6 16.5 5.1 16.5H17M17 13V16.5M9 19.5C9.8 19.5 10.5 20.2 10.5 21S9.8 22.5 9 22.5 7.5 21.8 7.5 21 8.2 19.5 9 19.5ZM20 19.5C20.8 19.5 21.5 20.2 21.5 21S20.8 22.5 20 22.5 18.5 21.8 18.5 21 19.2 19.5 20 19.5Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
{cart.itemCount > 0 && (
<span className="cart-badge">
{cart.itemCount > 99 ? '99+' : cart.itemCount}
</span>
)}
</button>
);
};

export default CartIcon;

🎯 AI编程助手最佳实践

1. 提示词优化技巧

有效的提示词模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# ❌ 模糊的提示
"写一个函数"

# ✅ 具体的提示
"写一个TypeScript函数,接收用户数组,按年龄排序,返回前10个最年轻的用户,包含错误处理和类型定义"

# ✅ 上下文丰富的提示
"在这个React电商项目中,创建一个产品搜索组件,支持:
- 实时搜索(防抖)
- 分类筛选
- 价格范围筛选
- 排序(价格、评分、销量)
- 分页
- 响应式设计
使用TypeScript和现有的UI组件库"

# ✅ 指定代码风格
"重构这个函数,使用函数式编程风格,避免副作用,添加JSDoc注释,遵循Clean Code原则"

上下文提供策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 提供相关代码片段
"基于以下API接口定义,生成对应的前端调用代码:
[粘贴API文档或接口定义]"

# 2. 说明项目架构
"这是一个使用Next.js + TypeScript + Tailwind CSS的项目,
采用原子设计模式,请创建一个符合项目规范的按钮组件"

# 3. 指定约束条件
"优化这个SQL查询,要求:
- 支持MySQL 8.0
- 查询时间小于100ms
- 避免全表扫描
- 保持结果准确性"

2. 代码质量保证

代码审查清单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 使用AI助手生成代码后的检查清单

// ✅ 类型安全
interface User {
id: string; // 明确的类型定义
name: string;
email: string;
createdAt: Date;
}

// ✅ 错误处理
const fetchUser = async (id: string): Promise<User | null> => {
try {
const response = await fetch(`/api/users/${id}`);

if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}

const user = await response.json();
return user;
} catch (error) {
console.error('Failed to fetch user:', error);
return null;
}
};

// ✅ 输入验证
const validateEmail = (email: string): boolean => {
if (!email || typeof email !== 'string') {
return false;
}

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};

// ✅ 性能优化
const MemoizedComponent = React.memo(({ data }: { data: User[] }) => {
const sortedData = useMemo(() => {
return data.sort((a, b) => a.name.localeCompare(b.name));
}, [data]);

return (
<div>
{sortedData.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
);
});

// ✅ 可测试性
export const userUtils = {
validateEmail,
fetchUser,
formatUserName: (user: User) => `${user.name} (${user.email})`
};

3. 安全性考虑

代码安全检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// ❌ 安全风险
const query = `SELECT * FROM users WHERE id = ${userId}`; // SQL注入风险
eval(userInput); // 代码注入风险
document.innerHTML = userContent; // XSS风险

// ✅ 安全实践
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]); // 参数化查询

// 输入验证和清理
const sanitizeInput = (input: string): string => {
return input
.replace(/[<>"'&]/g, '') // 移除危险字符
.trim()
.substring(0, 1000); // 限制长度
};

// 使用安全的DOM操作
const element = document.createElement('div');
element.textContent = userContent; // 自动转义

// 环境变量管理
const config = {
apiKey: process.env.API_KEY, // 不要硬编码密钥
dbUrl: process.env.DATABASE_URL
};

4. 团队协作规范

AI生成代码的团队规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
## AI编程助手使用规范

### 1. 代码生成后必须做的事情
- [ ] 代码审查和测试
- [ ] 添加适当的注释
- [ ] 检查安全性问题
- [ ] 验证性能影响
- [ ] 确保符合项目规范
- [ ] 更新相关文档

### 2. 提交信息规范
```bash
# ✅ 好的提交信息
git commit -m "feat: add user authentication with AI-generated validation logic

- Generated email validation function using GitHub Copilot
- Added password strength checker with Cursor assistance
- Implemented JWT token handling
- All AI-generated code reviewed and tested"

# ❌ 避免的提交信息
git commit -m "AI generated code"

3. 代码注释标准

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 用户认证服务
*
* @description 处理用户登录、注册和token管理
* @generated-by GitHub Copilot (reviewed and modified)
* @author 开发者姓名
* @version 1.0.0
*/
class AuthService {
/**
* 验证用户邮箱格式
*
* @param email - 用户邮箱地址
* @returns 验证结果
* @ai-assisted Copilot helped generate the regex pattern
*/
validateEmail(email: string): boolean {
// AI生成的正则表达式,已人工验证
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

---

## 📊 性能对比和选择建议

### 1. 功能对比矩阵

| 功能特性 | GitHub Copilot | Cursor | Codeium | Continue | Tabnine |
|----------|----------------|--------|---------|----------|----------|
| **代码补全准确率** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| **多语言支持** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| **对话编程** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ |
| **代码解释** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| **项目理解** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| **自定义能力** | ⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| **隐私保护** | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| **响应速度** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| **成本效益** | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |

### 2. 使用场景推荐

#### 🏢 企业开发团队
```markdown
**推荐组合**: GitHub Copilot + Tabnine

**理由**:
- GitHub Copilot: 主力代码生成,生态完善
- Tabnine: 本地运行,保护代码隐私
- 成本可控,符合企业安全要求

**配置建议**:
- 敏感项目使用Tabnine本地模式
- 开源项目使用GitHub Copilot
- 建立代码审查流程

👨‍💻 个人开发者

1
2
3
4
5
6
7
8
9
10
11
**推荐组合**: Codeium + Continue

**理由**:
- Codeium: 免费且功能强大
- Continue: 开源可定制
- 零成本获得专业AI编程体验

**配置建议**:
- 主要使用Codeium进行日常编程
- 使用Continue连接本地模型
- 学习阶段重点使用代码解释功能

🚀 初创公司

1
2
3
4
5
6
7
8
9
10
11
**推荐组合**: Cursor + Codeium

**理由**:
- Cursor: AI原生IDE,提升开发效率
- Codeium: 免费补充,降低成本
- 快速原型开发,适合敏捷开发

**配置建议**:
- 核心开发使用Cursor
- 辅助开发使用Codeium
- 重视代码质量和安全性

🎓 学习和教育

1
2
3
4
5
6
7
8
9
10
11
**推荐组合**: GitHub Copilot + Continue

**理由**:
- GitHub Copilot: 学生免费,代码质量高
- Continue: 开源学习,理解AI原理
- 教育价值高,有助于技能提升

**配置建议**:
- 使用GitHub Education获取免费Copilot
- 通过Continue学习AI编程原理
- 重点关注代码解释和学习功能

3. 成本效益分析

月度成本对比(美元)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
| 工具 | 个人版 | 团队版 | 企业版 | 备注 |
|------|--------|--------|--------|---------|
| **GitHub Copilot** | $10 | $19/用户 | 定制 | 学生免费 |
| **Cursor** | $20 | $40/用户 | 定制 | 2周免费试用 |
| **Codeium** | 免费 | $12/用户 | 定制 | 个人永久免费 |
| **Continue** | 免费 | 免费 | 免费 | 开源项目 |
| **Tabnine** | $12 | $19/用户 | 定制 | 本地运行选项 |

**年度成本计算**(10人团队):
- GitHub Copilot: $2,280
- Cursor: $4,800
- Codeium: $1,440
- Continue: $0
- Tabnine: $2,280

🛠️ 实战项目:构建AI辅助的全栈应用

项目概述

使用AI编程助手构建一个完整的任务管理应用,展示各种工具的实际应用效果。

技术栈

  • 前端: React + TypeScript + Tailwind CSS
  • 后端: Node.js + Express + TypeScript
  • 数据库: PostgreSQL + Prisma ORM
  • AI工具: GitHub Copilot + Cursor

1. 项目初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 使用AI助手生成项目脚手架
# 在Cursor中输入: "创建一个全栈TypeScript项目结构"

# 生成的项目结构
task-manager/
├── client/ # React前端
│ ├── src/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── pages/
│ │ ├── services/
│ │ ├── types/
│ │ └── utils/
│ ├── package.json
│ └── tsconfig.json
├── server/ # Node.js后端
│ ├── src/
│ │ ├── controllers/
│ │ ├── middleware/
│ │ ├── models/
│ │ ├── routes/
│ │ ├── services/
│ │ └── utils/
│ ├── package.json
│ └── tsconfig.json
├── shared/ # 共享类型定义
│ └── types/
├── docker-compose.yml
├── README.md
└── .gitignore

2. 数据库设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// prisma/schema.prisma
// 使用GitHub Copilot生成数据模型

generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model User {
id String @id @default(cuid())
email String @unique
name String
avatar String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

// 关联关系
tasks Task[]
projects ProjectMember[]

@@map("users")
}

model Project {
id String @id @default(cuid())
name String
description String?
color String @default("#3B82F6")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

// 关联关系
tasks Task[]
members ProjectMember[]

@@map("projects")
}

model ProjectMember {
id String @id @default(cuid())
role ProjectRole @default(MEMBER)
joinedAt DateTime @default(now())

// 外键
userId String
projectId String

// 关联关系
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)

@@unique([userId, projectId])
@@map("project_members")
}

model Task {
id String @id @default(cuid())
title String
description String?
status TaskStatus @default(TODO)
priority Priority @default(MEDIUM)
dueDate DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

// 外键
assigneeId String?
projectId String?

// 关联关系
assignee User? @relation(fields: [assigneeId], references: [id])
project Project? @relation(fields: [projectId], references: [id])

@@map("tasks")
}

enum TaskStatus {
TODO
IN_PROGRESS
REVIEW
DONE
}

enum Priority {
LOW
MEDIUM
HIGH
URGENT
}

enum ProjectRole {
OWNER
ADMIN
MEMBER
VIEWER
}

3. 后端API开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
// server/src/controllers/taskController.ts
// 使用Cursor生成完整的CRUD控制器

import { Request, Response } from 'express';
import { PrismaClient } from '@prisma/client';
import { z } from 'zod';
import { ApiResponse, PaginationParams } from '../types/api';
import { TaskStatus, Priority } from '../types/task';

const prisma = new PrismaClient();

// 验证模式
const createTaskSchema = z.object({
title: z.string().min(1).max(200),
description: z.string().optional(),
status: z.nativeEnum(TaskStatus).default(TaskStatus.TODO),
priority: z.nativeEnum(Priority).default(Priority.MEDIUM),
dueDate: z.string().datetime().optional(),
assigneeId: z.string().optional(),
projectId: z.string().optional()
});

const updateTaskSchema = createTaskSchema.partial();

const querySchema = z.object({
page: z.string().transform(Number).default('1'),
limit: z.string().transform(Number).default('10'),
status: z.nativeEnum(TaskStatus).optional(),
priority: z.nativeEnum(Priority).optional(),
assigneeId: z.string().optional(),
projectId: z.string().optional(),
search: z.string().optional()
});

export class TaskController {
/**
* 获取任务列表
* 支持分页、筛选和搜索
*/
static async getTasks(req: Request, res: Response): Promise<void> {
try {
const query = querySchema.parse(req.query);
const { page, limit, status, priority, assigneeId, projectId, search } = query;

const skip = (page - 1) * limit;

// 构建查询条件
const where: any = {};

if (status) where.status = status;
if (priority) where.priority = priority;
if (assigneeId) where.assigneeId = assigneeId;
if (projectId) where.projectId = projectId;

if (search) {
where.OR = [
{ title: { contains: search, mode: 'insensitive' } },
{ description: { contains: search, mode: 'insensitive' } }
];
}

// 并行查询数据和总数
const [tasks, total] = await Promise.all([
prisma.task.findMany({
where,
skip,
take: limit,
include: {
assignee: {
select: { id: true, name: true, email: true, avatar: true }
},
project: {
select: { id: true, name: true, color: true }
}
},
orderBy: [
{ priority: 'desc' },
{ createdAt: 'desc' }
]
}),
prisma.task.count({ where })
]);

const response: ApiResponse<typeof tasks> = {
success: true,
data: tasks,
pagination: {
page,
limit,
total,
pages: Math.ceil(total / limit)
}
};

res.json(response);
} catch (error) {
console.error('Error fetching tasks:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
}

/**
* 创建新任务
*/
static async createTask(req: Request, res: Response): Promise<void> {
try {
const validatedData = createTaskSchema.parse(req.body);

// 验证关联数据存在性
if (validatedData.assigneeId) {
const assignee = await prisma.user.findUnique({
where: { id: validatedData.assigneeId }
});
if (!assignee) {
res.status(400).json({
success: false,
error: 'Assignee not found'
});
return;
}
}

if (validatedData.projectId) {
const project = await prisma.project.findUnique({
where: { id: validatedData.projectId }
});
if (!project) {
res.status(400).json({
success: false,
error: 'Project not found'
});
return;
}
}

const task = await prisma.task.create({
data: {
...validatedData,
dueDate: validatedData.dueDate ? new Date(validatedData.dueDate) : null
},
include: {
assignee: {
select: { id: true, name: true, email: true, avatar: true }
},
project: {
select: { id: true, name: true, color: true }
}
}
});

res.status(201).json({
success: true,
data: task
});
} catch (error) {
if (error instanceof z.ZodError) {
res.status(400).json({
success: false,
error: 'Validation error',
details: error.errors
});
return;
}

console.error('Error creating task:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
}

/**
* 更新任务
*/
static async updateTask(req: Request, res: Response): Promise<void> {
try {
const { id } = req.params;
const validatedData = updateTaskSchema.parse(req.body);

// 检查任务是否存在
const existingTask = await prisma.task.findUnique({
where: { id }
});

if (!existingTask) {
res.status(404).json({
success: false,
error: 'Task not found'
});
return;
}

const task = await prisma.task.update({
where: { id },
data: {
...validatedData,
dueDate: validatedData.dueDate ? new Date(validatedData.dueDate) : undefined
},
include: {
assignee: {
select: { id: true, name: true, email: true, avatar: true }
},
project: {
select: { id: true, name: true, color: true }
}
}
});

res.json({
success: true,
data: task
});
} catch (error) {
if (error instanceof z.ZodError) {
res.status(400).json({
success: false,
error: 'Validation error',
details: error.errors
});
return;
}

console.error('Error updating task:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
}

/**
* 删除任务
*/
static async deleteTask(req: Request, res: Response): Promise<void> {
try {
const { id } = req.params;

const task = await prisma.task.findUnique({
where: { id }
});

if (!task) {
res.status(404).json({
success: false,
error: 'Task not found'
});
return;
}

await prisma.task.delete({
where: { id }
});

res.status(204).send();
} catch (error) {
console.error('Error deleting task:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
}

/**
* 获取任务统计信息
*/
static async getTaskStats(req: Request, res: Response): Promise<void> {
try {
const { projectId } = req.query;

const where = projectId ? { projectId: projectId as string } : {};

const [statusStats, priorityStats, totalTasks] = await Promise.all([
prisma.task.groupBy({
by: ['status'],
where,
_count: { status: true }
}),
prisma.task.groupBy({
by: ['priority'],
where,
_count: { priority: true }
}),
prisma.task.count({ where })
]);

res.json({
success: true,
data: {
total: totalTasks,
byStatus: statusStats.reduce((acc, item) => {
acc[item.status] = item._count.status;
return acc;
}, {} as Record<string, number>),
byPriority: priorityStats.reduce((acc, item) => {
acc[item.priority] = item._count.priority;
return acc;
}, {} as Record<string, number>)
}
});
} catch (error) {
console.error('Error fetching task stats:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
}
}