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,280 @@
|
|
|
1
|
+
# 问题诊断与修复规范
|
|
2
|
+
|
|
3
|
+
> **核心原则**:定位根因,精准修复,避免反复
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🎯 适用场景
|
|
8
|
+
|
|
9
|
+
- Bug 修复
|
|
10
|
+
- 样式问题调整
|
|
11
|
+
- 功能异常排查
|
|
12
|
+
- 性能问题优化
|
|
13
|
+
- 任何需要"修改"而非"新增"的场景
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## ⚠️ 常见错误模式
|
|
18
|
+
|
|
19
|
+
### 表面修复陷阱
|
|
20
|
+
|
|
21
|
+
| 表面现象 | 错误做法 | 真实原因示例 |
|
|
22
|
+
|----------|----------|--------------|
|
|
23
|
+
| 边框缺失 | 直接加 border | overflow:hidden 裁剪、多文件样式冲突、伪元素被隐藏 |
|
|
24
|
+
| 元素错位 | 调整 margin/padding | flex 布局问题、父容器约束、z-index 层级 |
|
|
25
|
+
| 点击无效 | 检查事件绑定 | 透明元素遮挡、pointer-events 设置、事件冒泡被阻止 |
|
|
26
|
+
| 文字截断 | 增加宽度 | white-space 设置、flex-shrink 压缩、父容器限制 |
|
|
27
|
+
| 动画卡顿 | 降低帧率 | 频繁重排重绘、JavaScript 阻塞、内存泄漏 |
|
|
28
|
+
| 接口超时 | 延长超时时间 | N+1 查询、缺少索引、死锁、资源竞争 |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 📋 强制诊断流程
|
|
33
|
+
|
|
34
|
+
### 第一步:复现与观察(必须)
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+
1. 完整复现问题,记录:
|
|
38
|
+
- 具体表现是什么?
|
|
39
|
+
- 在什么条件下出现?
|
|
40
|
+
- 是否稳定复现?
|
|
41
|
+
|
|
42
|
+
2. 收集环境信息:
|
|
43
|
+
- 浏览器/运行环境版本
|
|
44
|
+
- 相关依赖版本
|
|
45
|
+
- 是否仅在特定环境出现?
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 第二步:根因分析(核心)
|
|
49
|
+
|
|
50
|
+
**必须回答的问题**:
|
|
51
|
+
|
|
52
|
+
1. **谁**定义了这个行为?
|
|
53
|
+
- 哪个文件/哪一行代码?
|
|
54
|
+
- 是否有多处定义?(样式冲突常见原因)
|
|
55
|
+
|
|
56
|
+
2. **为什么**会这样表现?
|
|
57
|
+
- 这段代码的原始意图是什么?
|
|
58
|
+
- 当前表现与意图的差异在哪?
|
|
59
|
+
|
|
60
|
+
3. **什么时候**开始出现?
|
|
61
|
+
- 是一直存在还是最近才有?
|
|
62
|
+
- 如果最近才有,什么改动引入的?
|
|
63
|
+
|
|
64
|
+
4. **还有谁**可能受影响?
|
|
65
|
+
- 修改这里会影响其他地方吗?
|
|
66
|
+
- 是否有依赖这个行为的代码?
|
|
67
|
+
|
|
68
|
+
### 第三步:验证假设
|
|
69
|
+
|
|
70
|
+
```markdown
|
|
71
|
+
在修改前,必须验证你的假设:
|
|
72
|
+
|
|
73
|
+
✅ 正确做法:
|
|
74
|
+
- 使用浏览器开发者工具检查实际生效的样式
|
|
75
|
+
- 搜索全项目相关关键词,确认没有其他定义
|
|
76
|
+
- 临时注释可疑代码,观察变化
|
|
77
|
+
|
|
78
|
+
❌ 错误做法:
|
|
79
|
+
- 看一眼代码就下结论
|
|
80
|
+
- 不搜索直接修改
|
|
81
|
+
- 用 !important 强行覆盖
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 第四步:最小化修复
|
|
85
|
+
|
|
86
|
+
```markdown
|
|
87
|
+
修复原则:
|
|
88
|
+
1. 修改最少的代码
|
|
89
|
+
2. 从源头解决,而非末端补救
|
|
90
|
+
3. 不引入新的 hack 或 workaround
|
|
91
|
+
4. 保持代码一致性
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 🔍 诊断工具与方法
|
|
97
|
+
|
|
98
|
+
### 前端样式问题
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# 必做检查
|
|
102
|
+
1. DevTools → Elements → Computed 查看最终生效样式
|
|
103
|
+
2. DevTools → Elements → Styles 查看样式来源和覆盖关系
|
|
104
|
+
3. 全项目搜索相关选择器,检查是否有冲突定义
|
|
105
|
+
4. 检查父元素的 overflow、position、z-index
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 后端接口问题
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# 必做检查
|
|
112
|
+
1. 查看完整请求/响应日志
|
|
113
|
+
2. 检查数据库查询执行计划(EXPLAIN)
|
|
114
|
+
3. 检查是否有并发/锁问题
|
|
115
|
+
4. 检查资源使用情况(内存、连接池)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 通用代码问题
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# 必做检查
|
|
122
|
+
1. 使用 grep/ripgrep 搜索相关函数/变量的所有引用
|
|
123
|
+
2. 检查 git blame 了解代码变更历史
|
|
124
|
+
3. 查看相关测试用例(如果有)
|
|
125
|
+
4. 检查依赖库版本和已知问题
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 📝 修复报告模板
|
|
131
|
+
|
|
132
|
+
每次修复问题时,应在心中(或注释中)回答:
|
|
133
|
+
|
|
134
|
+
```markdown
|
|
135
|
+
## 问题描述
|
|
136
|
+
[具体表现]
|
|
137
|
+
|
|
138
|
+
## 根因分析
|
|
139
|
+
- 直接原因:[是什么导致了这个表现]
|
|
140
|
+
- 根本原因:[为什么会有这个直接原因]
|
|
141
|
+
- 影响范围:[这个问题还会影响哪些地方]
|
|
142
|
+
|
|
143
|
+
## 解决方案
|
|
144
|
+
- 修改内容:[具体改了什么]
|
|
145
|
+
- 为什么这样改:[而不是其他方案]
|
|
146
|
+
- 验证方法:[如何确认修复有效]
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 🚫 禁止事项
|
|
152
|
+
|
|
153
|
+
1. **禁止想当然修复**
|
|
154
|
+
- ❌ "边框没了?加个 border"
|
|
155
|
+
- ✅ "边框没了?先查为什么没了"
|
|
156
|
+
|
|
157
|
+
2. **禁止盲目使用 !important**
|
|
158
|
+
- ❌ 用 !important 强行覆盖
|
|
159
|
+
- ✅ 找到冲突源头,提高选择器优先级或删除冲突
|
|
160
|
+
|
|
161
|
+
3. **禁止不搜索就修改**
|
|
162
|
+
- ❌ 直接在当前文件修改
|
|
163
|
+
- ✅ 先搜索全项目相关定义
|
|
164
|
+
|
|
165
|
+
4. **禁止只看表面不查根因**
|
|
166
|
+
- ❌ 改了能跑就行
|
|
167
|
+
- ✅ 理解为什么会出问题
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 📚 真实案例
|
|
172
|
+
|
|
173
|
+
### 案例:Element Plus 表格边框问题
|
|
174
|
+
|
|
175
|
+
**表面现象**:表格边框显示不全,左边粗右边细
|
|
176
|
+
|
|
177
|
+
**错误修复路径**:
|
|
178
|
+
1. 加 `border: 1px solid` → 左边更粗了
|
|
179
|
+
2. 改 `overflow: hidden` → 右边消失了
|
|
180
|
+
3. 加伪元素边框 → 还是不对
|
|
181
|
+
|
|
182
|
+
**正确诊断**:
|
|
183
|
+
1. 搜索全项目 `.el-table--border` 相关样式
|
|
184
|
+
2. 发现 **两个文件** 都定义了表格边框:
|
|
185
|
+
- `table.css`: `border: 1px solid` + `::before { display: none }`
|
|
186
|
+
- `element-overrides.css`: `::before { background-color }`
|
|
187
|
+
3. 两套互相冲突的边框机制导致渲染异常
|
|
188
|
+
|
|
189
|
+
**正确修复**:
|
|
190
|
+
- 删除一处定义,保持单一来源
|
|
191
|
+
- 让 Element Plus 使用默认边框机制
|
|
192
|
+
|
|
193
|
+
**教训**:样式问题必须搜索全项目,确认没有冲突定义
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## 🎨 设计稿还原专项规范
|
|
198
|
+
|
|
199
|
+
> ⚠️ **此章节基于真实案例:一个输入框居中问题反复 15+ 轮对话才修复**
|
|
200
|
+
|
|
201
|
+
### 设计稿工具使用规范(Sketch/Figma)
|
|
202
|
+
|
|
203
|
+
#### 强制要求:完整读取选中元素及其所有子集
|
|
204
|
+
|
|
205
|
+
**问题根源**:
|
|
206
|
+
- 只读取了容器属性,忽略了内部文本的精确位置
|
|
207
|
+
- 每次只查询一个属性,导致信息不完整
|
|
208
|
+
- 假设而非验证具体数值
|
|
209
|
+
|
|
210
|
+
**正确做法**:
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
// 示例:读取输入框完整信息(包含所有子集)
|
|
214
|
+
function extractInputFieldComplete(inputGroup) {
|
|
215
|
+
console.log('=== 容器信息 ===');
|
|
216
|
+
console.log(`宽度: ${inputGroup.frame.width}px`);
|
|
217
|
+
console.log(`高度: ${inputGroup.frame.height}px`);
|
|
218
|
+
|
|
219
|
+
console.log('=== 内部文本(子集)===');
|
|
220
|
+
const text = inputGroup.layers.find(l => l.type === 'Text');
|
|
221
|
+
console.log(`文本 Y 坐标: ${text.frame.y}px`); // 关键:距容器顶部距离
|
|
222
|
+
console.log(`文本高度: ${text.frame.height}px`); // 关键:计算行高
|
|
223
|
+
console.log(`字号: ${text.style.fontSize}px`);
|
|
224
|
+
|
|
225
|
+
console.log('=== 计算结果 ===');
|
|
226
|
+
const topSpace = text.frame.y;
|
|
227
|
+
const bottomSpace = inputGroup.frame.height - text.frame.y - text.frame.height;
|
|
228
|
+
console.log(`上边距: ${topSpace}px`);
|
|
229
|
+
console.log(`下边距: ${bottomSpace}px`);
|
|
230
|
+
console.log(`行高倍数: ${(text.frame.height / text.style.fontSize).toFixed(2)}`);
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
#### 必须获取的信息清单
|
|
235
|
+
|
|
236
|
+
| 元素类型 | 必须获取 | 用途 |
|
|
237
|
+
|----------|----------|------|
|
|
238
|
+
| 容器 | width, height, padding | 外层尺寸 |
|
|
239
|
+
| 文本 | fontSize, Y坐标, height, fontWeight | 计算行高和边距 |
|
|
240
|
+
| 图标/SVG | viewBox, path, fill-opacity | 完整导出 |
|
|
241
|
+
| 渐变 | stops(所有节点), from, to | 精确还原 |
|
|
242
|
+
| 阴影 | x, y, blur, spread, color | 全部5个参数 |
|
|
243
|
+
|
|
244
|
+
### 反复修复问题的根因分析
|
|
245
|
+
|
|
246
|
+
| 导致反复的原因 | 正确做法 |
|
|
247
|
+
|----------------|----------|
|
|
248
|
+
| 只读取容器高度,不读内部文本 Y 坐标 | 一次性获取容器+所有子元素的完整信息 |
|
|
249
|
+
| 用"试错法"调整参数 | 先计算精确值(如行高=文本高度÷字号) |
|
|
250
|
+
| 修改 A 属性引发 B 问题 | 理解属性之间的相互作用关系 |
|
|
251
|
+
| 假设"差不多居中" | 从设计稿获取精确像素值验证 |
|
|
252
|
+
|
|
253
|
+
### 设计稿还原检查清单
|
|
254
|
+
|
|
255
|
+
修复任何设计还原问题前:
|
|
256
|
+
|
|
257
|
+
- [ ] 已获取目标元素的**完整信息**(容器+所有子集)
|
|
258
|
+
- [ ] 已计算精确数值(行高、边距、颜色透明度)
|
|
259
|
+
- [ ] 已理解框架渲染机制(如 Flutter TextField 的多属性相互作用)
|
|
260
|
+
- [ ] 一次性配置完整方案,而非逐个属性调整
|
|
261
|
+
- [ ] 验证所有相关元素(placeholder、光标、输入内容)都符合预期
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## ✅ 检查清单
|
|
266
|
+
|
|
267
|
+
修复任何问题前,确认以下检查项:
|
|
268
|
+
|
|
269
|
+
- [ ] 已搜索全项目相关代码
|
|
270
|
+
- [ ] 已确认没有其他文件定义相同/冲突的逻辑
|
|
271
|
+
- [ ] 已理解原代码的意图
|
|
272
|
+
- [ ] 修改方案从源头解决问题
|
|
273
|
+
- [ ] 修改不会影响其他功能
|
|
274
|
+
- [ ] 有明确的验证方法
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
**维护者**: MTA工作室
|
|
279
|
+
**创建日期**: 2025-01-04
|
|
280
|
+
**版本**: v1.0
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Flutter TextField 垂直居中纠错指南
|
|
2
|
+
|
|
3
|
+
> 本文档基于一次真实案例总结:修复一个简单的输入框垂直居中问题,经历了 **15+ 轮对话**,涉及多种方案反复尝试
|
|
4
|
+
|
|
5
|
+
## 📋 问题总结
|
|
6
|
+
|
|
7
|
+
### 问题描述
|
|
8
|
+
输入框需要实现 placeholder、光标、输入内容三者在容器中垂直居中对齐。
|
|
9
|
+
|
|
10
|
+
### 问题根因
|
|
11
|
+
Flutter TextField 的垂直对齐涉及**多个相互作用的属性**,修改一个属性可能影响其他元素的位置,导致"改了 A 问题引发 B 问题"的循环。
|
|
12
|
+
|
|
13
|
+
### 反复失败的原因
|
|
14
|
+
|
|
15
|
+
| 尝试次数 | 方案 | 结果 |
|
|
16
|
+
|----------|------|------|
|
|
17
|
+
| 1 | contentPadding: vertical: 10 | 整体偏下 |
|
|
18
|
+
| 2 | textAlignVertical: center | 只影响输入内容,placeholder 不动 |
|
|
19
|
+
| 3 | 移除 contentPadding | 整体偏上 |
|
|
20
|
+
| 4 | strutStyle + height: 1.0 | 文字被压缩,更难看 |
|
|
21
|
+
| 5 | Container.alignment + contentPadding: 8 | 输入内容正常,placeholder 偏下 |
|
|
22
|
+
| 6 | hintStyle height: 1.2 | placeholder 移动,但不够 |
|
|
23
|
+
| 7 | hintStyle height: 1.0 | placeholder 过于靠上 |
|
|
24
|
+
| 8-15 | 各种组合... | 来回折腾 |
|
|
25
|
+
|
|
26
|
+
### 根本问题
|
|
27
|
+
**没有一开始就理解 TextField 的渲染模型**,而是"试错式"调整参数。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## ✅ 正确方案(一步到位)
|
|
32
|
+
|
|
33
|
+
### 设计规格(从 Sketch 获取)
|
|
34
|
+
- 容器高度:36px
|
|
35
|
+
- 文本 Y 坐标:8px(距顶部)
|
|
36
|
+
- 文本高度:20px
|
|
37
|
+
- 字号:14px
|
|
38
|
+
- 行高倍数:1.43(20 ÷ 14 = 1.43)
|
|
39
|
+
|
|
40
|
+
### Flutter 正确配置
|
|
41
|
+
|
|
42
|
+
```dart
|
|
43
|
+
Widget _buildCenteredTextField({
|
|
44
|
+
required String placeholder,
|
|
45
|
+
required TextEditingController controller,
|
|
46
|
+
}) {
|
|
47
|
+
return Container(
|
|
48
|
+
height: 36,
|
|
49
|
+
decoration: BoxDecoration(
|
|
50
|
+
// ... 背景、圆角、阴影
|
|
51
|
+
),
|
|
52
|
+
alignment: Alignment.center, // 关键:让 TextField 在容器中居中
|
|
53
|
+
child: TextField(
|
|
54
|
+
controller: controller,
|
|
55
|
+
textAlign: TextAlign.center, // 水平居中
|
|
56
|
+
// 不要使用 textAlignVertical,会导致 placeholder 和输入内容位置不一致
|
|
57
|
+
style: const TextStyle(
|
|
58
|
+
fontSize: 14,
|
|
59
|
+
height: 1.43, // 关键:与 hintStyle 保持一致
|
|
60
|
+
fontWeight: FontWeight.w600,
|
|
61
|
+
),
|
|
62
|
+
decoration: InputDecoration(
|
|
63
|
+
hintText: placeholder,
|
|
64
|
+
hintStyle: const TextStyle(
|
|
65
|
+
fontSize: 14,
|
|
66
|
+
height: 1.43, // 关键:与 style 完全一致
|
|
67
|
+
fontWeight: FontWeight.w600,
|
|
68
|
+
),
|
|
69
|
+
contentPadding: EdgeInsets.zero, // 关键:清除默认 padding
|
|
70
|
+
isDense: true, // 关键:移除额外空间
|
|
71
|
+
border: InputBorder.none,
|
|
72
|
+
enabledBorder: InputBorder.none,
|
|
73
|
+
focusedBorder: InputBorder.none,
|
|
74
|
+
),
|
|
75
|
+
),
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 关键原则
|
|
81
|
+
|
|
82
|
+
| 属性 | 作用 | 注意事项 |
|
|
83
|
+
|------|------|----------|
|
|
84
|
+
| `Container.alignment: Alignment.center` | 让 TextField 整体在容器中居中 | 必须配合 `contentPadding: EdgeInsets.zero` |
|
|
85
|
+
| `style.height` 和 `hintStyle.height` | 控制行高 | **必须相同**,否则 placeholder 和输入内容位置不一致 |
|
|
86
|
+
| `contentPadding: EdgeInsets.zero` | 清除默认间距 | 让 Container.alignment 生效 |
|
|
87
|
+
| `isDense: true` | 移除 TextField 默认空间 | 减少干扰因素 |
|
|
88
|
+
| `textAlignVertical` | **不推荐使用** | 只影响输入内容,不影响 placeholder |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 📌 简版纠错指南
|
|
93
|
+
|
|
94
|
+
### TextField 垂直居中三步法
|
|
95
|
+
|
|
96
|
+
```dart
|
|
97
|
+
// Step 1: Container 提供高度和居中
|
|
98
|
+
Container(
|
|
99
|
+
height: 36,
|
|
100
|
+
alignment: Alignment.center,
|
|
101
|
+
child: TextField(
|
|
102
|
+
// Step 2: style 和 hintStyle 使用相同的 height
|
|
103
|
+
style: TextStyle(fontSize: 14, height: 1.43),
|
|
104
|
+
decoration: InputDecoration(
|
|
105
|
+
hintStyle: TextStyle(fontSize: 14, height: 1.43),
|
|
106
|
+
// Step 3: 清除 padding,启用 isDense
|
|
107
|
+
contentPadding: EdgeInsets.zero,
|
|
108
|
+
isDense: true,
|
|
109
|
+
),
|
|
110
|
+
),
|
|
111
|
+
)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 禁止事项
|
|
115
|
+
|
|
116
|
+
1. ❌ **禁止 style.height 和 hintStyle.height 不一致** - 会导致 placeholder 和输入内容位置不同
|
|
117
|
+
2. ❌ **禁止同时使用 textAlignVertical 和 height** - 会产生冲突
|
|
118
|
+
3. ❌ **禁止 strutStyle + forceStrutHeight** - 可能压缩文字
|
|
119
|
+
4. ❌ **禁止反复调整 contentPadding 试错** - 先确定行高配置
|
|
120
|
+
|
|
121
|
+
### 调试顺序
|
|
122
|
+
|
|
123
|
+
遇到 TextField 垂直对齐问题时,按以下顺序检查:
|
|
124
|
+
|
|
125
|
+
1. **先确认设计规格** - 容器高度、文本高度、计算行高倍数
|
|
126
|
+
2. **配置 height** - style 和 hintStyle 使用相同的 height
|
|
127
|
+
3. **配置 Container** - alignment: Alignment.center
|
|
128
|
+
4. **清除干扰** - contentPadding: EdgeInsets.zero, isDense: true
|
|
129
|
+
5. **移除冲突属性** - 不要用 textAlignVertical 和 strutStyle
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 🎯 案例复盘
|
|
134
|
+
|
|
135
|
+
### 为什么需要 15+ 轮对话?
|
|
136
|
+
|
|
137
|
+
| 问题 | 正确做法 |
|
|
138
|
+
|------|----------|
|
|
139
|
+
| 没有先计算行高倍数 | 从设计稿提取:文本高度 ÷ 字号 = height |
|
|
140
|
+
| 逐个尝试属性 | 一次性配置完整方案 |
|
|
141
|
+
| 改了 A 引发 B | 理解属性之间的关系 |
|
|
142
|
+
| 没有统一 style 和 hintStyle | 两者必须完全一致 |
|
|
143
|
+
|
|
144
|
+
### 正确的工作流
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
1. 从 Sketch 获取完整规格(容器高度、文本 Y 坐标、文本高度)
|
|
148
|
+
2. 计算 height = 文本高度 ÷ 字号
|
|
149
|
+
3. 一次性配置完整方案(Container.alignment + 相同 height + contentPadding.zero + isDense)
|
|
150
|
+
4. 验证三者(placeholder、光标、输入内容)是否对齐
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
**创建日期**: 2026-01-19
|
|
156
|
+
**案例来源**: 汇款记录筛选弹窗金额输入框
|
|
157
|
+
**解决方案**: Container.alignment + 统一 height + contentPadding.zero
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# 📦 项目模板代码库
|
|
2
|
+
|
|
3
|
+
> 预置的可复用代码模板,支持快速生成项目基础设施
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🤖 Agent 使用指令
|
|
8
|
+
|
|
9
|
+
当用户说出以下类似指令时,Agent 应按照本文档规范执行:
|
|
10
|
+
|
|
11
|
+
**触发指令示例**:
|
|
12
|
+
- "将 axios 模板应用到 ht-manage 项目"
|
|
13
|
+
- "把 api-layer 模板复制到 VitaSage"
|
|
14
|
+
- "给 xx 项目配置 API 层"
|
|
15
|
+
- "应用 vue/api-layer 模板"
|
|
16
|
+
|
|
17
|
+
**Agent 执行流程**:
|
|
18
|
+
|
|
19
|
+
1. **识别模板** - 根据关键词匹配模板:
|
|
20
|
+
| 关键词 | 对应模板 |
|
|
21
|
+
|--------|----------|
|
|
22
|
+
| axios / api / api-layer / 请求封装 | `vue/api-layer` |
|
|
23
|
+
| types / 类型 | `common/types` |
|
|
24
|
+
|
|
25
|
+
2. **确定目标路径** - 根据项目和模板类型:
|
|
26
|
+
| 模板 | 目标路径 |
|
|
27
|
+
|------|----------|
|
|
28
|
+
| `vue/api-layer` | `{项目}/src/api/` |
|
|
29
|
+
| `common/types` | `{项目}/src/types/` |
|
|
30
|
+
|
|
31
|
+
3. **复制文件** - 将模板目录下的文件(排除 `_CONFIG.md`)复制到目标路径
|
|
32
|
+
|
|
33
|
+
4. **提示配置** - 告知用户需要根据 `_CONFIG.md` 调整的配置项:
|
|
34
|
+
- UI 框架适配(showMessage)
|
|
35
|
+
- 后端响应格式适配
|
|
36
|
+
- Token 传递方式
|
|
37
|
+
- 环境变量配置
|
|
38
|
+
|
|
39
|
+
**执行示例**:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
用户: 将 axios 模板应用到 ht-manage 项目
|
|
43
|
+
|
|
44
|
+
Agent 执行:
|
|
45
|
+
1. 模板路径: /Users/pailasi/Work/copilot-prompts/templates/vue/api-layer/
|
|
46
|
+
2. 目标路径: /Users/pailasi/Work/ht-manage/src/api/
|
|
47
|
+
3. 复制文件:
|
|
48
|
+
- request.ts
|
|
49
|
+
- types.ts
|
|
50
|
+
- index.ts
|
|
51
|
+
- mock/index.ts
|
|
52
|
+
- modules/index.ts
|
|
53
|
+
- modules/_template.ts
|
|
54
|
+
4. 提示用户按 _CONFIG.md 配置
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 目录结构
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
templates/
|
|
63
|
+
├── README.md # 本文件(含 Agent 指令)
|
|
64
|
+
├── vue/ # Vue 项目模板
|
|
65
|
+
│ ├── api-layer/ # API 层封装(axios + mock)✅
|
|
66
|
+
│ ├── composables/ # 通用 Composables(预留)
|
|
67
|
+
│ ├── components/ # 通用组件模板(预留)
|
|
68
|
+
│ └── stores/ # 状态管理模板(预留)
|
|
69
|
+
├── flutter/ # Flutter 项目模板(预留)
|
|
70
|
+
│ ├── api-layer/
|
|
71
|
+
│ └── themes/
|
|
72
|
+
├── react/ # React 项目模板(预留)
|
|
73
|
+
└── common/ # 跨框架通用模板
|
|
74
|
+
└── types/ # TypeScript 类型定义 ✅
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 🎯 手动使用方式
|
|
80
|
+
|
|
81
|
+
1. 进入对应模板目录
|
|
82
|
+
2. 复制需要的文件到项目中
|
|
83
|
+
3. 根据 `_CONFIG.md` 文件说明进行配置
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 📋 可用模板
|
|
88
|
+
|
|
89
|
+
### Vue 项目
|
|
90
|
+
|
|
91
|
+
| 模板 | 关键词 | 说明 | 状态 |
|
|
92
|
+
|------|--------|------|------|
|
|
93
|
+
| `vue/api-layer` | axios, api, 请求封装 | Axios + Mock 完整封装 | ✅ 可用 |
|
|
94
|
+
| `vue/composables` | composable, hook | 通用 Composables | 🚧 计划中 |
|
|
95
|
+
| `vue/components` | component, 组件 | 基础组件模板 | 🚧 计划中 |
|
|
96
|
+
| `vue/stores` | pinia, store, 状态 | Pinia Store 模板 | 🚧 计划中 |
|
|
97
|
+
|
|
98
|
+
### Flutter 项目
|
|
99
|
+
|
|
100
|
+
| 模板 | 关键词 | 说明 | 状态 |
|
|
101
|
+
|------|--------|------|------|
|
|
102
|
+
| `flutter/api-layer` | dio, api | Dio + 状态管理封装 | 🚧 计划中 |
|
|
103
|
+
| `flutter/themes` | theme, token | Design Token 系统 | 🚧 计划中 |
|
|
104
|
+
|
|
105
|
+
### 通用模板
|
|
106
|
+
|
|
107
|
+
| 模板 | 关键词 | 说明 | 状态 |
|
|
108
|
+
|------|--------|------|------|
|
|
109
|
+
| `common/types` | types, 类型 | TypeScript 通用类型 | ✅ 可用 |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 🔧 模板规范
|
|
114
|
+
|
|
115
|
+
每个模板目录必须包含:
|
|
116
|
+
|
|
117
|
+
1. **`_CONFIG.md`** - 配置说明文件
|
|
118
|
+
- 模板用途
|
|
119
|
+
- 依赖要求
|
|
120
|
+
- 配置项说明
|
|
121
|
+
- 适配指南
|
|
122
|
+
|
|
123
|
+
2. **源代码文件** - 可直接复制使用的代码
|
|
124
|
+
- 保持通用性,不含业务逻辑
|
|
125
|
+
- 标注自定义点(使用 `💡` 或 `TODO` 注释)
|
|
126
|
+
- 支持多种配置方案
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 🚀 扩展模板
|
|
131
|
+
|
|
132
|
+
添加新模板时:
|
|
133
|
+
|
|
134
|
+
1. 在对应框架目录下创建模板文件夹
|
|
135
|
+
2. 编写 `_CONFIG.md` 配置说明
|
|
136
|
+
3. 添加代码文件,确保通用性
|
|
137
|
+
4. 更新本 README 的模板列表
|
|
138
|
+
5. 如有相关规范文档,在 `standards/patterns/` 中添加
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
**维护者**: MTA工作室
|
|
143
|
+
**创建日期**: 2025-12-25
|
|
144
|
+
**版本**: v1.0
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API 相关类型定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** API 响应基础结构 */
|
|
6
|
+
export interface ApiResponse<T = any> {
|
|
7
|
+
code: number
|
|
8
|
+
data: T
|
|
9
|
+
message: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** 分页参数 */
|
|
13
|
+
export interface PageParams {
|
|
14
|
+
page: number
|
|
15
|
+
pageSize: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** 分页数据 */
|
|
19
|
+
export interface PageData<T> {
|
|
20
|
+
list: T[]
|
|
21
|
+
total: number
|
|
22
|
+
page: number
|
|
23
|
+
pageSize: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** 分页响应 */
|
|
27
|
+
export type PageResponse<T> = ApiResponse<PageData<T>>
|
|
28
|
+
|
|
29
|
+
/** 排序参数 */
|
|
30
|
+
export interface SortParams {
|
|
31
|
+
sortField?: string
|
|
32
|
+
sortOrder?: 'asc' | 'desc'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** 时间范围 */
|
|
36
|
+
export interface DateRange {
|
|
37
|
+
startDate?: string
|
|
38
|
+
endDate?: string
|
|
39
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 通用业务类型定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** 通用 ID 类型 */
|
|
6
|
+
export type ID = string | number
|
|
7
|
+
|
|
8
|
+
/** 通用状态 */
|
|
9
|
+
export type Status = 'active' | 'inactive' | 'pending' | 'deleted'
|
|
10
|
+
|
|
11
|
+
/** 启用状态 */
|
|
12
|
+
export type EnableStatus = 0 | 1
|
|
13
|
+
|
|
14
|
+
/** 审核状态 */
|
|
15
|
+
export type AuditStatus = 'pending' | 'approved' | 'rejected'
|
|
16
|
+
|
|
17
|
+
/** 性别 */
|
|
18
|
+
export type Gender = 'male' | 'female' | 'unknown'
|
|
19
|
+
|
|
20
|
+
/** 键值对 */
|
|
21
|
+
export interface KeyValue<T = any> {
|
|
22
|
+
key: string
|
|
23
|
+
value: T
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** 选项项(下拉框等) */
|
|
27
|
+
export interface OptionItem<T = string | number> {
|
|
28
|
+
label: string
|
|
29
|
+
value: T
|
|
30
|
+
disabled?: boolean
|
|
31
|
+
children?: OptionItem<T>[]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** 树形节点 */
|
|
35
|
+
export interface TreeNode<T = any> {
|
|
36
|
+
id: ID
|
|
37
|
+
label: string
|
|
38
|
+
children?: TreeNode<T>[]
|
|
39
|
+
data?: T
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** 表格列配置 */
|
|
43
|
+
export interface TableColumn {
|
|
44
|
+
prop: string
|
|
45
|
+
label: string
|
|
46
|
+
width?: number | string
|
|
47
|
+
minWidth?: number | string
|
|
48
|
+
fixed?: 'left' | 'right'
|
|
49
|
+
sortable?: boolean
|
|
50
|
+
align?: 'left' | 'center' | 'right'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** 用户基础信息 */
|
|
54
|
+
export interface UserBase {
|
|
55
|
+
id: ID
|
|
56
|
+
username: string
|
|
57
|
+
nickname?: string
|
|
58
|
+
avatar?: string
|
|
59
|
+
email?: string
|
|
60
|
+
phone?: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** 带时间戳的基础实体 */
|
|
64
|
+
export interface BaseEntity {
|
|
65
|
+
id: ID
|
|
66
|
+
createdAt: string
|
|
67
|
+
updatedAt: string
|
|
68
|
+
createdBy?: ID
|
|
69
|
+
updatedBy?: ID
|
|
70
|
+
}
|