mta-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +818 -0
- package/agents/_TEMPLATE.md +153 -0
- package/agents/flutter.agent.md +222 -0
- package/agents/i18n.agent.md +78 -0
- package/agents/logicflow.agent.md +97 -0
- package/agents/vue3.agent.md +176 -0
- package/agents/wechat-miniprogram.agent.md +89 -0
- package/bin/mta.cjs +132 -0
- package/common/i18n.md +385 -0
- package/common/typescript-strict.md +186 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.js +6493 -0
- package/dist/index.js.map +1 -0
- package/package.json +81 -0
- package/standards/README.md +194 -0
- package/standards/core/code-generation.md +421 -0
- package/standards/core/code-style.md +308 -0
- package/standards/core/dart-base.md +572 -0
- package/standards/core/mandatory-rules.md +103 -0
- package/standards/core/typescript-base.md +179 -0
- package/standards/frameworks/flutter-ui-system.md +497 -0
- package/standards/frameworks/flutter.md +1268 -0
- package/standards/frameworks/pinia.md +172 -0
- package/standards/frameworks/vue3-composition.md +779 -0
- package/standards/frameworks/wechat-miniprogram.md +2177 -0
- package/standards/libraries/element-plus.md +1128 -0
- package/standards/libraries/i18n.md +360 -0
- package/standards/libraries/logicflow.md +1007 -0
- package/standards/patterns/api-layer.md +187 -0
- package/standards/patterns/component-design.md +200 -0
- package/standards/patterns/design-system-restoration.md +570 -0
- package/standards/patterns/vue-api-mock-layer.md +958 -0
- package/standards/patterns/vue-css-nesting.md +604 -0
- package/standards/troubleshooting-cases/flutter/textfield-vertical-centering.md +107 -0
- package/standards/workflows/design-restoration-guide.md +164 -0
- package/standards/workflows/large-project-split.md +359 -0
- package/standards/workflows/problem-diagnosis.md +280 -0
- package/standards/workflows/textfield-centering-guide.md +157 -0
- package/templates/README.md +144 -0
- package/templates/common/types/_CONFIG.md +12 -0
- package/templates/common/types/api.ts +39 -0
- package/templates/common/types/common.ts +70 -0
- package/templates/config-templates/agents-section.md +9 -0
- package/templates/config-templates/custom-section.md +6 -0
- package/templates/config-templates/header.md +29 -0
- package/templates/config-templates/workflow-minimal.md +44 -0
- package/templates/copilot-instructions-mcp-optimized.md +158 -0
- package/templates/vue/api-layer/_CONFIG.md +145 -0
- package/templates/vue/api-layer/index.ts +58 -0
- package/templates/vue/api-layer/mock/index.ts +122 -0
- package/templates/vue/api-layer/modules/_template.ts +109 -0
- package/templates/vue/api-layer/modules/index.ts +16 -0
- package/templates/vue/api-layer/request.ts +279 -0
- package/templates/vue/api-layer/types.ts +80 -0
- package/troubleshooting/README.md +368 -0
- package/troubleshooting/USAGE_GUIDE.md +289 -0
- package/troubleshooting/flutter/clip-/351/230/264/345/275/261/350/243/201/345/211/252.md +244 -0
- package/troubleshooting/flutter/component-/351/200/232/347/224/250/345/214/226/346/217/220/345/217/226.md +269 -0
- package/troubleshooting/flutter/input-/345/255/227/346/256/265/347/274/272/345/244/261.md +240 -0
- package/troubleshooting/flutter/input-/350/276/271/346/241/206/351/227/256/351/242/230.md +236 -0
- package/troubleshooting/flutter/layout-/345/260/272/345/257/270/344/270/215/345/214/271/351/205/215.md +214 -0
- package/troubleshooting/flutter/shadow-/351/200/217/345/207/272/351/227/256/351/242/230.md +172 -0
- package/troubleshooting/flutter/sketch-/345/210/227/350/241/250item/345/214/272/345/237/237.md +212 -0
- package/troubleshooting/flutter/sketch-/345/233/276/346/240/207/345/260/272/345/257/270.md +135 -0
- package/troubleshooting/flutter/sketch-/345/256/214/346/225/264/346/217/220/345/217/226.md +201 -0
- package/troubleshooting/flutter/sketch-/345/261/236/346/200/247/346/234/252/344/275/277/347/224/250.md +139 -0
- package/troubleshooting/flutter/sketch-/350/203/214/346/231/257/345/261/202/351/253/230/345/272/246.md +264 -0
- package/troubleshooting/flutter/svg-/346/234/252/345/261/205/344/270/255.md +120 -0
- package/troubleshooting/flutter/svg-/351/242/234/350/211/262/345/274/202/345/270/270.md +117 -0
- package/troubleshooting/flutter/tabbar-/345/212/250/347/224/273/345/220/214/346/255/245.md +107 -0
- package/troubleshooting/flutter/withopacity-/345/274/203/347/224/250.md +81 -0
- package/troubleshooting/vue3/cascader-/350/257/257/346/233/277/346/215/242.md +130 -0
- package/troubleshooting/vue3/drawer-input-/346/240/267/345/274/217.md +181 -0
- package/troubleshooting/vue3/table-/347/274/226/350/276/221/345/217/226/346/266/210.md +148 -0
- package/troubleshooting/vue3/table-/350/276/271/346/241/206/351/227/256/351/242/230.md +178 -0
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
# Dart 基础规范
|
|
2
|
+
|
|
3
|
+
> 基于 [Effective Dart](https://dart.dev/effective-dart) 和 Flutter 官方最佳实践
|
|
4
|
+
|
|
5
|
+
## 核心原则
|
|
6
|
+
|
|
7
|
+
1. **类型安全优先** - 充分利用 Dart 的类型系统和空安全特性
|
|
8
|
+
2. **简洁清晰** - 代码应当简洁但不失可读性
|
|
9
|
+
3. **函数式风格** - 优先使用函数式和声明式编程模式
|
|
10
|
+
4. **不可变性** - 优先使用不可变数据结构
|
|
11
|
+
5. **测试优先** - 编写可测试的代码
|
|
12
|
+
|
|
13
|
+
## 类型系统
|
|
14
|
+
|
|
15
|
+
### 空安全 (Null Safety)
|
|
16
|
+
|
|
17
|
+
```dart
|
|
18
|
+
// ✅ 好 - 充分利用空安全
|
|
19
|
+
String? nullableString;
|
|
20
|
+
String nonNullableString = 'Hello';
|
|
21
|
+
|
|
22
|
+
// 使用 null 检查
|
|
23
|
+
if (nullableString != null) {
|
|
24
|
+
print(nullableString.length);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 使用 null-aware 操作符
|
|
28
|
+
final length = nullableString?.length ?? 0;
|
|
29
|
+
|
|
30
|
+
// ❌ 坏 - 避免使用 ! 除非确定非空
|
|
31
|
+
final length = nullableString!.length; // 危险!
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 类型推断
|
|
35
|
+
|
|
36
|
+
```dart
|
|
37
|
+
// ✅ 好 - 让 Dart 推断明显的类型
|
|
38
|
+
var name = 'John';
|
|
39
|
+
var count = 42;
|
|
40
|
+
final items = <String>[];
|
|
41
|
+
|
|
42
|
+
// ✅ 好 - 显式声明不明显的类型
|
|
43
|
+
String? getUserName() => null;
|
|
44
|
+
final String? username = getUserName();
|
|
45
|
+
|
|
46
|
+
// ❌ 坏 - 过度类型标注
|
|
47
|
+
String name = 'John'; // 不必要
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 泛型
|
|
51
|
+
|
|
52
|
+
```dart
|
|
53
|
+
// ✅ 好 - 使用泛型保证类型安全
|
|
54
|
+
class Box<T> {
|
|
55
|
+
final T value;
|
|
56
|
+
Box(this.value);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
final stringBox = Box<String>('Hello');
|
|
60
|
+
|
|
61
|
+
// 泛型方法
|
|
62
|
+
T first<T>(List<T> items) => items.first;
|
|
63
|
+
|
|
64
|
+
// ❌ 坏 - 避免使用 dynamic
|
|
65
|
+
class Box {
|
|
66
|
+
final dynamic value; // 失去类型安全
|
|
67
|
+
Box(this.value);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 函数与方法
|
|
72
|
+
|
|
73
|
+
### 函数定义
|
|
74
|
+
|
|
75
|
+
```dart
|
|
76
|
+
// ✅ 好 - 清晰的参数和返回类型
|
|
77
|
+
int add(int a, int b) => a + b;
|
|
78
|
+
|
|
79
|
+
// 命名参数
|
|
80
|
+
String greet({
|
|
81
|
+
required String name,
|
|
82
|
+
String title = '',
|
|
83
|
+
}) {
|
|
84
|
+
return title.isEmpty ? name : '$title $name';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 可选位置参数
|
|
88
|
+
String formatDate(DateTime date, [String format = 'yyyy-MM-dd']) {
|
|
89
|
+
// 实现
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 异步编程
|
|
94
|
+
|
|
95
|
+
```dart
|
|
96
|
+
// ✅ 好 - 正确使用 async/await
|
|
97
|
+
Future<User?> fetchUser(String id) async {
|
|
98
|
+
try {
|
|
99
|
+
final response = await http.get(Uri.parse('/api/users/$id'));
|
|
100
|
+
if (response.statusCode == 200) {
|
|
101
|
+
return User.fromJson(jsonDecode(response.body));
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
} catch (e) {
|
|
105
|
+
print('Error fetching user: $e');
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ✅ 好 - 使用 Stream 处理事件序列
|
|
111
|
+
Stream<int> countStream(int max) async* {
|
|
112
|
+
for (var i = 0; i < max; i++) {
|
|
113
|
+
await Future.delayed(Duration(seconds: 1));
|
|
114
|
+
yield i;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ❌ 坏 - 忘记 await
|
|
119
|
+
Future<void> saveUser(User user) async {
|
|
120
|
+
database.save(user); // 忘记 await!
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 箭头函数
|
|
125
|
+
|
|
126
|
+
```dart
|
|
127
|
+
// ✅ 好 - 单行函数使用箭头语法
|
|
128
|
+
int square(int x) => x * x;
|
|
129
|
+
bool get isValid => value > 0 && value < 100;
|
|
130
|
+
|
|
131
|
+
// ✅ 好 - 复杂逻辑使用函数体
|
|
132
|
+
String formatName(String first, String last) {
|
|
133
|
+
final firstName = first.trim();
|
|
134
|
+
final lastName = last.trim();
|
|
135
|
+
return '$lastName, $firstName';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ❌ 坏 - 过度复杂的箭头函数
|
|
139
|
+
String formatName(String first, String last) =>
|
|
140
|
+
'${last.trim()}, ${first.trim().toUpperCase()}'; // 难以阅读
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## 类与对象
|
|
144
|
+
|
|
145
|
+
### 类定义
|
|
146
|
+
|
|
147
|
+
```dart
|
|
148
|
+
// ✅ 好 - 清晰的类结构
|
|
149
|
+
class User {
|
|
150
|
+
// 1. 构造函数首先
|
|
151
|
+
User({
|
|
152
|
+
required this.id,
|
|
153
|
+
required this.name,
|
|
154
|
+
this.email,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// 2. 命名构造函数
|
|
158
|
+
User.guest() : id = 0, name = 'Guest', email = null;
|
|
159
|
+
|
|
160
|
+
// 3. 字段
|
|
161
|
+
final int id;
|
|
162
|
+
final String name;
|
|
163
|
+
final String? email;
|
|
164
|
+
|
|
165
|
+
// 4. Getters
|
|
166
|
+
bool get hasEmail => email != null;
|
|
167
|
+
|
|
168
|
+
// 5. 方法
|
|
169
|
+
Map<String, dynamic> toJson() => {
|
|
170
|
+
'id': id,
|
|
171
|
+
'name': name,
|
|
172
|
+
'email': email,
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// 6. 重写方法
|
|
176
|
+
@override
|
|
177
|
+
String toString() => 'User($id: $name)';
|
|
178
|
+
|
|
179
|
+
@override
|
|
180
|
+
bool operator ==(Object other) =>
|
|
181
|
+
identical(this, other) ||
|
|
182
|
+
other is User &&
|
|
183
|
+
runtimeType == other.runtimeType &&
|
|
184
|
+
id == other.id;
|
|
185
|
+
|
|
186
|
+
@override
|
|
187
|
+
int get hashCode => id.hashCode;
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 不可变类
|
|
192
|
+
|
|
193
|
+
```dart
|
|
194
|
+
// ✅ 好 - 使用不可变数据
|
|
195
|
+
class Point {
|
|
196
|
+
const Point(this.x, this.y);
|
|
197
|
+
|
|
198
|
+
final double x;
|
|
199
|
+
final double y;
|
|
200
|
+
|
|
201
|
+
// 返回新实例而不是修改
|
|
202
|
+
Point translate(double dx, double dy) =>
|
|
203
|
+
Point(x + dx, y + dy);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ❌ 坏 - 可变状态
|
|
207
|
+
class Point {
|
|
208
|
+
Point(this.x, this.y);
|
|
209
|
+
|
|
210
|
+
double x;
|
|
211
|
+
double y;
|
|
212
|
+
|
|
213
|
+
void translate(double dx, double dy) {
|
|
214
|
+
x += dx;
|
|
215
|
+
y += dy;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## 模式匹配
|
|
221
|
+
|
|
222
|
+
### Switch 表达式和语句
|
|
223
|
+
|
|
224
|
+
```dart
|
|
225
|
+
// ✅ 好 - 使用 switch 表达式
|
|
226
|
+
String getStatusMessage(Status status) => switch (status) {
|
|
227
|
+
Status.pending => '等待中',
|
|
228
|
+
Status.running => '运行中',
|
|
229
|
+
Status.completed => '已完成',
|
|
230
|
+
Status.failed => '失败',
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// ✅ 好 - 模式匹配
|
|
234
|
+
String describe(Object obj) => switch (obj) {
|
|
235
|
+
int() => '整数',
|
|
236
|
+
String() => '字符串',
|
|
237
|
+
List<int>() => '整数列表',
|
|
238
|
+
_ => '其他类型',
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// ✅ 好 - 解构
|
|
242
|
+
void processUser(User user) {
|
|
243
|
+
final User(:name, :email) = user;
|
|
244
|
+
print('$name: ${email ?? "无邮箱"}');
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Records (记录类型)
|
|
249
|
+
|
|
250
|
+
```dart
|
|
251
|
+
// ✅ 好 - 使用 Record 返回多个值
|
|
252
|
+
(int, String) getUserInfo() => (42, 'John');
|
|
253
|
+
|
|
254
|
+
// 命名字段
|
|
255
|
+
({int age, String name}) getDetailedUserInfo() =>
|
|
256
|
+
(age: 42, name: 'John');
|
|
257
|
+
|
|
258
|
+
// 解构使用
|
|
259
|
+
final (age, name) = getUserInfo();
|
|
260
|
+
final (:age, :name) = getDetailedUserInfo();
|
|
261
|
+
|
|
262
|
+
// ❌ 坏 - 为简单返回定义完整的类
|
|
263
|
+
class UserInfo {
|
|
264
|
+
final int age;
|
|
265
|
+
final String name;
|
|
266
|
+
UserInfo(this.age, this.name);
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## 集合
|
|
271
|
+
|
|
272
|
+
### 列表操作
|
|
273
|
+
|
|
274
|
+
```dart
|
|
275
|
+
// ✅ 好 - 使用函数式方法
|
|
276
|
+
final numbers = [1, 2, 3, 4, 5];
|
|
277
|
+
|
|
278
|
+
final doubled = numbers.map((n) => n * 2).toList();
|
|
279
|
+
final evens = numbers.where((n) => n.isEven).toList();
|
|
280
|
+
final sum = numbers.reduce((a, b) => a + b);
|
|
281
|
+
|
|
282
|
+
// ✅ 好 - 集合字面量
|
|
283
|
+
final names = <String>['Alice', 'Bob'];
|
|
284
|
+
final scores = <String, int>{'Alice': 90, 'Bob': 85};
|
|
285
|
+
final uniqueIds = <int>{1, 2, 3};
|
|
286
|
+
|
|
287
|
+
// ✅ 好 - 集合 if 和 for
|
|
288
|
+
final items = [
|
|
289
|
+
'Home',
|
|
290
|
+
if (isLoggedIn) 'Profile',
|
|
291
|
+
if (isAdmin) 'Admin Panel',
|
|
292
|
+
for (var category in categories) category.name,
|
|
293
|
+
];
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Spread 操作符
|
|
297
|
+
|
|
298
|
+
```dart
|
|
299
|
+
// ✅ 好 - 使用 spread 操作符
|
|
300
|
+
final first = [1, 2, 3];
|
|
301
|
+
final second = [4, 5, 6];
|
|
302
|
+
final combined = [...first, ...second];
|
|
303
|
+
|
|
304
|
+
// null-aware spread
|
|
305
|
+
final List<int>? optional = null;
|
|
306
|
+
final result = [...first, ...?optional]; // [1, 2, 3]
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## 错误处理
|
|
310
|
+
|
|
311
|
+
### 异常处理
|
|
312
|
+
|
|
313
|
+
```dart
|
|
314
|
+
// ✅ 好 - 具体的异常类型
|
|
315
|
+
class ValidationException implements Exception {
|
|
316
|
+
final String message;
|
|
317
|
+
ValidationException(this.message);
|
|
318
|
+
|
|
319
|
+
@override
|
|
320
|
+
String toString() => 'ValidationException: $message';
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ✅ 好 - 适当的 try-catch
|
|
324
|
+
Future<void> processData(String data) async {
|
|
325
|
+
try {
|
|
326
|
+
final parsed = jsonDecode(data);
|
|
327
|
+
await saveToDatabase(parsed);
|
|
328
|
+
} on FormatException catch (e) {
|
|
329
|
+
print('Invalid JSON format: $e');
|
|
330
|
+
rethrow;
|
|
331
|
+
} on DatabaseException catch (e, stackTrace) {
|
|
332
|
+
print('Database error: $e');
|
|
333
|
+
print(stackTrace);
|
|
334
|
+
throw ProcessingException('Failed to save data');
|
|
335
|
+
} finally {
|
|
336
|
+
cleanup();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// ❌ 坏 - 捕获所有异常却不处理
|
|
341
|
+
try {
|
|
342
|
+
dangerousOperation();
|
|
343
|
+
} catch (e) {
|
|
344
|
+
// 空的 catch 块 - 隐藏错误!
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## 命名规范
|
|
349
|
+
|
|
350
|
+
### 标识符命名
|
|
351
|
+
|
|
352
|
+
```dart
|
|
353
|
+
// ✅ 好 - 清晰的命名
|
|
354
|
+
class UserProfile {} // UpperCamelCase 类名
|
|
355
|
+
void fetchUserData() {} // lowerCamelCase 函数/方法
|
|
356
|
+
const maxRetryCount = 3; // lowerCamelCase 常量
|
|
357
|
+
enum NetworkStatus {} // UpperCamelCase 枚举
|
|
358
|
+
final _privateField = 0; // 下划线开头表示私有
|
|
359
|
+
|
|
360
|
+
// 文件名使用 snake_case
|
|
361
|
+
// user_profile.dart
|
|
362
|
+
// network_service.dart
|
|
363
|
+
|
|
364
|
+
// ❌ 坏 - 不清晰的命名
|
|
365
|
+
class UP {} // 缩写不清晰
|
|
366
|
+
void fetchUD() {} // 缩写不清晰
|
|
367
|
+
const MAX_RETRY = 3; // Dart 不使用 SCREAMING_CAPS
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### 布尔值命名
|
|
371
|
+
|
|
372
|
+
```dart
|
|
373
|
+
// ✅ 好 - 使用 is/has/can 等前缀
|
|
374
|
+
bool isValid;
|
|
375
|
+
bool hasPermission;
|
|
376
|
+
bool canEdit;
|
|
377
|
+
bool shouldRetry;
|
|
378
|
+
|
|
379
|
+
// ❌ 坏
|
|
380
|
+
bool valid; // 不够清晰
|
|
381
|
+
bool permission; // 听起来不像布尔值
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## 断言和调试
|
|
385
|
+
|
|
386
|
+
### 使用 assert
|
|
387
|
+
|
|
388
|
+
```dart
|
|
389
|
+
// ✅ 好 - 使用 assert 验证不变量
|
|
390
|
+
class Rectangle {
|
|
391
|
+
Rectangle(this.width, this.height)
|
|
392
|
+
: assert(width > 0, 'Width must be positive'),
|
|
393
|
+
assert(height > 0, 'Height must be positive');
|
|
394
|
+
|
|
395
|
+
final double width;
|
|
396
|
+
final double height;
|
|
397
|
+
|
|
398
|
+
double get area {
|
|
399
|
+
assert(!width.isNaN && !height.isNaN);
|
|
400
|
+
return width * height;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// ✅ 好 - 调试时的断言
|
|
405
|
+
void processItems(List<Item> items) {
|
|
406
|
+
assert(() {
|
|
407
|
+
// 复杂的验证逻辑,仅在 debug 模式运行
|
|
408
|
+
for (final item in items) {
|
|
409
|
+
if (!item.isValid) {
|
|
410
|
+
print('Invalid item found: $item');
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return true;
|
|
415
|
+
}());
|
|
416
|
+
|
|
417
|
+
// 处理逻辑...
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## 文档注释
|
|
422
|
+
|
|
423
|
+
### DartDoc 风格
|
|
424
|
+
|
|
425
|
+
```dart
|
|
426
|
+
/// 计算两个数的和。
|
|
427
|
+
///
|
|
428
|
+
/// 接受两个整数参数 [a] 和 [b],返回它们的和。
|
|
429
|
+
///
|
|
430
|
+
/// 示例:
|
|
431
|
+
/// ```dart
|
|
432
|
+
/// final result = add(2, 3);
|
|
433
|
+
/// print(result); // 输出: 5
|
|
434
|
+
/// ```
|
|
435
|
+
int add(int a, int b) => a + b;
|
|
436
|
+
|
|
437
|
+
/// 表示应用程序中的用户。
|
|
438
|
+
///
|
|
439
|
+
/// [User] 是不可变的,包含用户的基本信息。
|
|
440
|
+
/// 使用 [User.guest] 创建访客用户。
|
|
441
|
+
///
|
|
442
|
+
/// 另见:
|
|
443
|
+
/// * [UserProfile] - 用户的详细资料
|
|
444
|
+
/// * [UserRepository] - 用户数据访问
|
|
445
|
+
class User {
|
|
446
|
+
/// 创建新用户实例。
|
|
447
|
+
///
|
|
448
|
+
/// [id] 和 [name] 是必需的。
|
|
449
|
+
/// [email] 是可选的。
|
|
450
|
+
User({
|
|
451
|
+
required this.id,
|
|
452
|
+
required this.name,
|
|
453
|
+
this.email,
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
/// 用户的唯一标识符。
|
|
457
|
+
final int id;
|
|
458
|
+
|
|
459
|
+
/// 用户的显示名称。
|
|
460
|
+
final String name;
|
|
461
|
+
|
|
462
|
+
/// 用户的电子邮件地址(可选)。
|
|
463
|
+
final String? email;
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
## 避免的模式
|
|
468
|
+
|
|
469
|
+
### ❌ 避免使用 dynamic
|
|
470
|
+
|
|
471
|
+
```dart
|
|
472
|
+
// ❌ 坏 - 失去类型安全
|
|
473
|
+
dynamic data = fetchData();
|
|
474
|
+
print(data.length); // 运行时才知道是否出错
|
|
475
|
+
|
|
476
|
+
// ✅ 好 - 使用具体类型或泛型
|
|
477
|
+
Object data = fetchData();
|
|
478
|
+
if (data is String) {
|
|
479
|
+
print(data.length);
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### ❌ 避免过度使用 extension
|
|
484
|
+
|
|
485
|
+
```dart
|
|
486
|
+
// ❌ 坏 - 不必要的 extension
|
|
487
|
+
extension StringExtension on String {
|
|
488
|
+
String capitalize() => this[0].toUpperCase() + substring(1);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// ✅ 好 - 使用普通函数
|
|
492
|
+
String capitalize(String str) =>
|
|
493
|
+
str[0].toUpperCase() + str.substring(1);
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### ❌ 避免 part/part of
|
|
497
|
+
|
|
498
|
+
```dart
|
|
499
|
+
// ❌ 坏 - 避免使用 part/part of
|
|
500
|
+
// file1.dart
|
|
501
|
+
part of 'main.dart';
|
|
502
|
+
|
|
503
|
+
// ✅ 好 - 使用 import/export
|
|
504
|
+
// file1.dart
|
|
505
|
+
class MyClass {}
|
|
506
|
+
|
|
507
|
+
// main.dart
|
|
508
|
+
import 'file1.dart';
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
## 性能建议
|
|
512
|
+
|
|
513
|
+
### 避免不必要的计算
|
|
514
|
+
|
|
515
|
+
```dart
|
|
516
|
+
// ✅ 好 - 缓存计算结果
|
|
517
|
+
class Rectangle {
|
|
518
|
+
Rectangle(this.width, this.height);
|
|
519
|
+
|
|
520
|
+
final double width;
|
|
521
|
+
final double height;
|
|
522
|
+
|
|
523
|
+
late final double area = width * height; // 只计算一次
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// ❌ 坏 - 重复计算
|
|
527
|
+
class Rectangle {
|
|
528
|
+
Rectangle(this.width, this.height);
|
|
529
|
+
|
|
530
|
+
final double width;
|
|
531
|
+
final double height;
|
|
532
|
+
|
|
533
|
+
double get area => width * height; // 每次访问都计算
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
### 使用 const 构造函数
|
|
538
|
+
|
|
539
|
+
```dart
|
|
540
|
+
// ✅ 好 - 使用 const 减少内存分配
|
|
541
|
+
class Color {
|
|
542
|
+
const Color(this.r, this.g, this.b);
|
|
543
|
+
|
|
544
|
+
final int r, g, b;
|
|
545
|
+
|
|
546
|
+
static const red = Color(255, 0, 0);
|
|
547
|
+
static const blue = Color(0, 0, 255);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// 使用时
|
|
551
|
+
const widget = Icon(icon: Icons.home, color: Color.red);
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
## 最佳实践总结
|
|
555
|
+
|
|
556
|
+
1. **充分利用空安全** - 明确区分可空和非空类型
|
|
557
|
+
2. **优先使用不可变数据** - 使用 `final` 和 `const`
|
|
558
|
+
3. **编写简洁的代码** - 但不牺牲可读性
|
|
559
|
+
4. **使用模式匹配** - switch 表达式和解构
|
|
560
|
+
5. **适当的异常处理** - 使用具体的异常类型
|
|
561
|
+
6. **编写文档注释** - 为公共 API 提供清晰的文档
|
|
562
|
+
7. **使用断言验证** - 在开发时捕获错误
|
|
563
|
+
8. **遵循命名规范** - 保持代码一致性
|
|
564
|
+
9. **测试优先** - 编写可测试的代码
|
|
565
|
+
10. **性能意识** - 使用 const、缓存等优化技巧
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
**参考资源:**
|
|
570
|
+
- [Effective Dart](https://dart.dev/effective-dart)
|
|
571
|
+
- [Dart Language Tour](https://dart.dev/language)
|
|
572
|
+
- [Flutter Style Guide](https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 底层必须规则(Mandatory Rules)
|
|
2
|
+
|
|
3
|
+
> 此规范由 MCP 底层自动注入,所有规范请求都会附加此内容。
|
|
4
|
+
> 版本: v1.0.0 | 最后更新: 2026-01-16
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 🚨 零容忍规则
|
|
9
|
+
|
|
10
|
+
**这些规则在任何情况下都不能违反,优先级最高:**
|
|
11
|
+
|
|
12
|
+
### 1. 完整的标签配对
|
|
13
|
+
|
|
14
|
+
```html
|
|
15
|
+
✅ <div>...</div>
|
|
16
|
+
✅ <el-table>...</el-table>
|
|
17
|
+
❌ <div>...<div> <!-- 缺少结束标签 -->
|
|
18
|
+
❌ </div> <!-- 孤立的结束标签 -->
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. 禁止 `any` 类型
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// ❌ 禁止
|
|
25
|
+
const data: any = {}
|
|
26
|
+
function process(input: any) {}
|
|
27
|
+
|
|
28
|
+
// ✅ 正确
|
|
29
|
+
const data: Record<string, unknown> = {}
|
|
30
|
+
function process(input: UserData) {}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 3. 国际化强制使用
|
|
34
|
+
|
|
35
|
+
```vue
|
|
36
|
+
<!-- ✅ 正确 -->
|
|
37
|
+
<el-button>{{ $t('提交') }}</el-button>
|
|
38
|
+
:label="$t('名称')"
|
|
39
|
+
:placeholder="$t('请输入')"
|
|
40
|
+
|
|
41
|
+
<!-- ❌ 硬编码 -->
|
|
42
|
+
<el-button>提交</el-button>
|
|
43
|
+
label="名称"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## ⚠️ 强制工作流
|
|
49
|
+
|
|
50
|
+
### 问题诊断优先
|
|
51
|
+
|
|
52
|
+
当用户描述问题时(错误、样式不对、效果不符预期),必须先调用:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
troubleshoot({ problem: "用户描述的问题" })
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 规范加载验证
|
|
59
|
+
|
|
60
|
+
在生成代码前,必须确认已加载相关规范:
|
|
61
|
+
|
|
62
|
+
1. **检查项目作用域** - 确认文件路径属于当前项目
|
|
63
|
+
2. **声明已加载** - 在响应中说明:`✅ 已加载规范: [规范名称]`
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🔍 代码审查清单
|
|
68
|
+
|
|
69
|
+
**每次编辑后必检:**
|
|
70
|
+
|
|
71
|
+
- [ ] 所有 HTML 标签正确闭合
|
|
72
|
+
- [ ] Vue SFC 只有一个 `<style>` 标签
|
|
73
|
+
- [ ] 所有用户可见文本已国际化
|
|
74
|
+
- [ ] 无 `any` 类型
|
|
75
|
+
- [ ] Props/Emits 有完整类型定义
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 🚫 全局禁止模式
|
|
80
|
+
|
|
81
|
+
| 禁止 | 替代方案 |
|
|
82
|
+
|------|----------|
|
|
83
|
+
| `any` 类型 | 具体类型或 `unknown` |
|
|
84
|
+
| Options API | Composition API (`<script setup>`) |
|
|
85
|
+
| 直接修改 Props | emit 事件或 computed |
|
|
86
|
+
| `<script>` 中使用 `this` | 使用响应式变量 |
|
|
87
|
+
| 多个 `<style>` 标签 | 合并为一个 |
|
|
88
|
+
| 硬编码文本 | `$t('...')` 国际化 |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 📋 最小改动原则
|
|
93
|
+
|
|
94
|
+
| 判断项 | 是 | 否 |
|
|
95
|
+
|--------|---|---|
|
|
96
|
+
| 修改只影响当前文件? | 继续修改 | **停止,重新评估** |
|
|
97
|
+
| 存在类似模式? | **复用现有模式** | 可新建 |
|
|
98
|
+
| 需要改组件类型? | **先确认用户意图** | 继续 |
|
|
99
|
+
| 需要删除现有代码? | **先确认必要性** | 继续 |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
**此规范自动注入,无需手动加载。**
|