zhuge-workflow 0.1.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/dist/index.js +801 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
- package/templates/claude/CLAUDE-ccg.md +258 -0
- package/templates/claude/CLAUDE.md +106 -0
- package/templates/claude/commands/ccg/_context.md +152 -0
- package/templates/claude/commands/ccg/spec-impl.md +161 -0
- package/templates/claude/commands/ccg/spec-plan-trellis.md +239 -0
- package/templates/claude/commands/ccg/spec-plan.md +225 -0
- package/templates/claude/commands/ccg/spec-research.md +113 -0
- package/templates/claude/commands/ccg/spec-review.md +127 -0
- package/templates/claude/commands/developer/brainstorm.md +5 -0
- package/templates/claude/commands/developer/design-checklist.md +81 -0
- package/templates/claude/commands/developer/design-doc.md +188 -0
- package/templates/claude/commands/developer/requirement-doc.md +150 -0
- package/templates/claude/commands/developer/requirement-interrogate.md +71 -0
- package/templates/claude/commands/developer/status.md +55 -0
- package/templates/claude/rules/bash-style.md +46 -0
- package/templates/claude/rules/claude-code-defensive.md +99 -0
- package/templates/claude/rules/doc-sync.md +49 -0
- package/templates/claude/rules/ops-safety.md +32 -0
- package/templates/claude/skills/bash-style/SKILL.md +244 -0
- package/templates/claude/skills/brainstorming/SKILL.md +48 -0
- package/templates/claude/skills/dotnet-dev/SKILL.md +250 -0
- package/templates/claude/skills/dotnet-dev/references/dotnet-style.md +991 -0
- package/templates/claude/skills/mcp-builder/LICENSE.txt +202 -0
- package/templates/claude/skills/mcp-builder/SKILL.md +328 -0
- package/templates/claude/skills/mcp-builder/reference/evaluation.md +602 -0
- package/templates/claude/skills/mcp-builder/reference/mcp_best_practices.md +915 -0
- package/templates/claude/skills/mcp-builder/reference/node_mcp_server.md +916 -0
- package/templates/claude/skills/mcp-builder/reference/python_mcp_server.md +752 -0
- package/templates/claude/skills/mcp-builder/scripts/connections.py +151 -0
- package/templates/claude/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/templates/claude/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/templates/claude/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/templates/claude/skills/ops-safety/SKILL.md +130 -0
- package/templates/claude/skills/python-dev/SKILL.md +281 -0
- package/templates/claude/skills/skill-creator/LICENSE.txt +202 -0
- package/templates/claude/skills/skill-creator/SKILL.md +209 -0
- package/templates/claude/skills/skill-creator/scripts/init_skill.py +303 -0
- package/templates/claude/skills/skill-creator/scripts/package_skill.py +110 -0
- package/templates/claude/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/templates/claude/skills/sqlserver-executor/SKILL.md +201 -0
- package/templates/claude/skills/sqlserver-executor/assets/config-example.json +26 -0
- package/templates/claude/skills/sqlserver-executor/config.json +12 -0
- package/templates/claude/skills/sqlserver-executor/scripts/sql_executor.py +404 -0
- package/templates/claude/skills/ui-ux-pro-max/SKILL.md +228 -0
- package/templates/claude/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/templates/claude/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/templates/claude/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/templates/claude/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/templates/claude/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/templates/claude/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/templates/claude/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/templates/claude/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/templates/claude/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/templates/claude/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
- package/templates/claude/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/templates/claude/skills/ui-ux-pro-max/scripts/core.py +238 -0
- package/templates/claude/skills/ui-ux-pro-max/scripts/search.py +61 -0
- package/templates/claude/skills/webapp-testing/LICENSE.txt +202 -0
- package/templates/claude/skills/webapp-testing/SKILL.md +96 -0
- package/templates/claude/skills/webapp-testing/examples/console_logging.py +35 -0
- package/templates/claude/skills/webapp-testing/examples/element_discovery.py +40 -0
- package/templates/claude/skills/webapp-testing/examples/static_html_automation.py +33 -0
- package/templates/claude/skills/webapp-testing/scripts/with_server.py +106 -0
- package/templates/init/claude-agents/ccg-impl.md +199 -0
- package/templates/init/claude-agents/ccg-review.md +146 -0
- package/templates/init/claude-agents/dispatch.md +253 -0
- package/templates/init/claude-hooks/inject-subagent-context.py +964 -0
- package/templates/init/trellis-scripts/task.sh +1326 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bash-style
|
|
3
|
+
description: 当用户操作 .sh、Dockerfile、Makefile、.yml、.yaml 文件,或在 Markdown 中编写 bash 代码块时触发。提供 Bash 编写规范。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Bash 编写规范
|
|
7
|
+
|
|
8
|
+
版本:v1.0
|
|
9
|
+
更新:2026-01
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. 注释规范
|
|
14
|
+
|
|
15
|
+
### 禁止行尾注释
|
|
16
|
+
|
|
17
|
+
- ❌ **禁止行尾注释**(如 `command # 注释`)
|
|
18
|
+
- ✅ 注释应独占一行,放在代码上方
|
|
19
|
+
|
|
20
|
+
**适用范围**:
|
|
21
|
+
- Shell 脚本文件(.sh)
|
|
22
|
+
- Markdown 文档中的 bash 代码块
|
|
23
|
+
- Dockerfile、Makefile 中的 shell 命令
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# ❌ 错误:行尾注释
|
|
27
|
+
curl -X POST https://api.example.com/data # 发送请求
|
|
28
|
+
docker run -d nginx # 启动容器
|
|
29
|
+
cp -r src/ dist/ # 复制文件
|
|
30
|
+
|
|
31
|
+
# ✅ 正确:注释独占一行
|
|
32
|
+
# 发送请求
|
|
33
|
+
curl -X POST https://api.example.com/data
|
|
34
|
+
|
|
35
|
+
# 启动容器
|
|
36
|
+
docker run -d nginx
|
|
37
|
+
|
|
38
|
+
# 复制文件
|
|
39
|
+
cp -r src/ dist/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**原因**:
|
|
43
|
+
- 复制粘贴时容易带上注释导致命令出错
|
|
44
|
+
- 长命令 + 注释 = 超长行,可读性差
|
|
45
|
+
- Heredoc 块内 `#` 不是注释而是内容
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. 文件写入方式
|
|
50
|
+
|
|
51
|
+
### 推荐方式:tee 命令
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# ✅ 推荐:简洁、无嵌套引号
|
|
55
|
+
sudo tee /etc/fail2ban/jail.d/docker-nginx.local > /dev/null << 'EOF'
|
|
56
|
+
[docker-nginx]
|
|
57
|
+
enabled = true
|
|
58
|
+
filter = docker-nginx
|
|
59
|
+
logpath = /var/log/nginx/access.log
|
|
60
|
+
maxretry = 5
|
|
61
|
+
EOF
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 追加内容
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# ✅ 追加到文件
|
|
68
|
+
sudo tee -a /etc/hosts > /dev/null << 'EOF'
|
|
69
|
+
192.168.1.100 myserver
|
|
70
|
+
EOF
|
|
71
|
+
|
|
72
|
+
# ✅ 单行追加
|
|
73
|
+
echo '192.168.1.100 myserver' | sudo tee -a /etc/hosts
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 避免的写法
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# ❌ 避免:嵌套引号复杂,易出错
|
|
80
|
+
sudo bash -c 'cat > /etc/xxx << EOF
|
|
81
|
+
content
|
|
82
|
+
EOF'
|
|
83
|
+
|
|
84
|
+
# ❌ 避免:需要转义内容中的特殊字符
|
|
85
|
+
sudo sh -c "echo 'line1\nline2' > /etc/xxx"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 方式对比
|
|
89
|
+
|
|
90
|
+
| 方式 | 优点 | 缺点 | 推荐场景 |
|
|
91
|
+
|------|------|------|---------|
|
|
92
|
+
| `sudo tee` | 简洁、无嵌套 | 需 `> /dev/null` 抑制输出 | **首选** |
|
|
93
|
+
| `sudo bash -c 'cat >'` | 无需 tee | 嵌套引号复杂 | 不推荐 |
|
|
94
|
+
| 临时文件 + mv | 可先验证 | 步骤多 | 复杂配置 |
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 3. Heredoc 引号规则
|
|
99
|
+
|
|
100
|
+
### 禁止变量展开(推荐默认)
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# ✅ 'EOF' 带引号:内容原样输出,不解析变量
|
|
104
|
+
sudo tee /etc/xxx > /dev/null << 'EOF'
|
|
105
|
+
$HOME 不会被展开
|
|
106
|
+
$(command) 不会被执行
|
|
107
|
+
EOF
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 需要变量展开
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# EOF 不带引号:变量会被展开
|
|
114
|
+
sudo tee /etc/xxx > /dev/null << EOF
|
|
115
|
+
当前用户: $USER
|
|
116
|
+
当前目录: $(pwd)
|
|
117
|
+
EOF
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 选择原则
|
|
121
|
+
|
|
122
|
+
| 场景 | 用法 | 原因 |
|
|
123
|
+
|------|------|------|
|
|
124
|
+
| 配置文件 | `<< 'EOF'` | 避免意外展开 |
|
|
125
|
+
| 模板生成 | `<< EOF` | 需要插入变量 |
|
|
126
|
+
| 不确定时 | `<< 'EOF'` | 更安全 |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 4. 权限与路径
|
|
131
|
+
|
|
132
|
+
### 需要 root 权限
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# ✅ 正确:tee 配合 sudo
|
|
136
|
+
echo 'content' | sudo tee /etc/xxx
|
|
137
|
+
|
|
138
|
+
# ❌ 错误:重定向在 sudo 之外,权限不足
|
|
139
|
+
sudo echo 'content' > /etc/xxx
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 路径带空格
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# ✅ 正确:双引号包裹路径
|
|
146
|
+
sudo tee "/etc/my config/file.conf" > /dev/null << 'EOF'
|
|
147
|
+
content
|
|
148
|
+
EOF
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 5. 脚本规范
|
|
154
|
+
|
|
155
|
+
### 文件头
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
#!/usr/bin/env bash
|
|
159
|
+
set -euo pipefail
|
|
160
|
+
|
|
161
|
+
# 脚本说明(一句话)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### set 选项说明
|
|
165
|
+
|
|
166
|
+
| 选项 | 作用 |
|
|
167
|
+
|------|------|
|
|
168
|
+
| `-e` | 命令失败时退出 |
|
|
169
|
+
| `-u` | 使用未定义变量时报错 |
|
|
170
|
+
| `-o pipefail` | 管道中任一命令失败则整体失败 |
|
|
171
|
+
|
|
172
|
+
### 变量使用
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# ✅ 推荐:使用 ${} 包裹
|
|
176
|
+
echo "Hello, ${name}"
|
|
177
|
+
|
|
178
|
+
# ✅ 推荐:设置默认值
|
|
179
|
+
db_host="${DB_HOST:-localhost}"
|
|
180
|
+
|
|
181
|
+
# ❌ 避免:裸变量(易与后续字符混淆)
|
|
182
|
+
echo "Hello, $name_suffix"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 6. 常用模式
|
|
188
|
+
|
|
189
|
+
### 检查命令是否存在
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
if ! command -v docker &> /dev/null; then
|
|
193
|
+
echo "docker 未安装"
|
|
194
|
+
exit 1
|
|
195
|
+
fi
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### 检查文件/目录
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# 文件存在
|
|
202
|
+
[[ -f /path/to/file ]] && echo "文件存在"
|
|
203
|
+
|
|
204
|
+
# 目录存在
|
|
205
|
+
[[ -d /path/to/dir ]] || mkdir -p /path/to/dir
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 安全删除
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
# ✅ 使用变量时防止误删
|
|
212
|
+
rm -rf "${dir:?}"/*
|
|
213
|
+
|
|
214
|
+
# ❌ 危险:变量为空时会删除根目录
|
|
215
|
+
rm -rf $dir/*
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 7. 文档中的代码块
|
|
221
|
+
|
|
222
|
+
在 Markdown 文档中编写 bash 命令时,同样遵循以上规范:
|
|
223
|
+
|
|
224
|
+
````markdown
|
|
225
|
+
## 安装配置
|
|
226
|
+
|
|
227
|
+
创建配置文件:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
sudo tee /etc/myapp/config.yml > /dev/null << 'EOF'
|
|
231
|
+
server:
|
|
232
|
+
port: 8080
|
|
233
|
+
host: 0.0.0.0
|
|
234
|
+
EOF
|
|
235
|
+
```
|
|
236
|
+
````
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## 参考资料
|
|
241
|
+
|
|
242
|
+
- [Google Shell Style Guide](https://google.github.io/styleguide/shellguide.html)
|
|
243
|
+
- [Bash Pitfalls](https://mywiki.wooledge.org/BashPitfalls)
|
|
244
|
+
- [ShellCheck](https://www.shellcheck.net/)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brainstorming
|
|
3
|
+
description: "在任何创意工作之前必须使用此技能 - 包括头脑风暴、功能设计、需求分析、创建功能、构建组件、添加功能或修改行为或提及想开发一个/想做一个等相关语义相近时。任何跟功能设计探讨时需使用。在实现之前探索用户意图、需求和设计。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 头脑风暴:从想法到设计
|
|
7
|
+
|
|
8
|
+
## 概述
|
|
9
|
+
|
|
10
|
+
通过自然的协作对话,帮助将想法转化为完整的设计和规格说明。
|
|
11
|
+
|
|
12
|
+
首先了解当前项目上下文,然后逐一提问以完善想法。一旦理解要构建的内容,分小节(200-300 词)呈现设计,每节之后确认目前是否正确。
|
|
13
|
+
|
|
14
|
+
## 流程
|
|
15
|
+
|
|
16
|
+
**理解想法:**
|
|
17
|
+
- 首先查看当前项目状态(文件、文档、最近提交)
|
|
18
|
+
- 逐一提问以完善想法
|
|
19
|
+
- 尽可能使用选择题,开放式问题也可以
|
|
20
|
+
- 每条消息只问一个问题 - 如果某个主题需要深入探索,拆分为多个问题
|
|
21
|
+
- 聚焦于理解:目的、约束条件、成功标准
|
|
22
|
+
|
|
23
|
+
**探索方案:**
|
|
24
|
+
- 提出 2-3 种不同方案及其权衡取舍
|
|
25
|
+
- 以对话方式呈现选项,附上你的推荐和理由
|
|
26
|
+
- 先给出推荐方案并解释原因
|
|
27
|
+
|
|
28
|
+
**呈现设计:**
|
|
29
|
+
- 一旦你认为理解了要构建的内容,呈现设计
|
|
30
|
+
- 分成 200-300 词的小节
|
|
31
|
+
- 每节之后询问目前是否正确
|
|
32
|
+
- 涵盖:架构、组件、数据流、错误处理、测试
|
|
33
|
+
- 如有不清楚的地方,随时返回澄清
|
|
34
|
+
|
|
35
|
+
## 设计完成后
|
|
36
|
+
|
|
37
|
+
**文档:**
|
|
38
|
+
|
|
39
|
+
- 将验证通过的设计写入 `.claude/brainstorming-plan/YYYY-MM-DD-<主题>-design.md`
|
|
40
|
+
|
|
41
|
+
## 核心原则
|
|
42
|
+
|
|
43
|
+
- **一次一问** - 不要用多个问题让人应接不暇
|
|
44
|
+
- **优先选择题** - 在可能的情况下,比开放式问题更容易回答
|
|
45
|
+
- **严格遵循 YAGNI** - 从所有设计中移除不必要的功能
|
|
46
|
+
- **探索替代方案** - 在确定之前始终提出 2-3 种方案
|
|
47
|
+
- **增量验证** - 分节呈现设计,逐节验证
|
|
48
|
+
- **保持灵活** - 当某处不合理时,返回澄清
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dotnet-dev
|
|
3
|
+
description: .NET Core 开发规范,包含命名约定、异常处理、Furion + SqlSugar 最佳实践等
|
|
4
|
+
version: v3.0
|
|
5
|
+
paths:
|
|
6
|
+
- "**/*.cs"
|
|
7
|
+
- "**/*.csproj"
|
|
8
|
+
- "**/*.sln"
|
|
9
|
+
- "**/appsettings.json"
|
|
10
|
+
- "**/appsettings.*.json"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# .NET Core 开发规范
|
|
14
|
+
|
|
15
|
+
> 参考来源: Microsoft C# 编码约定、Furion 官方文档
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 工具链
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# dotnet CLI
|
|
23
|
+
dotnet build # 编译
|
|
24
|
+
dotnet test # 运行测试
|
|
25
|
+
dotnet run # 运行项目
|
|
26
|
+
dotnet publish -c Release # 发布
|
|
27
|
+
|
|
28
|
+
# 格式化与分析
|
|
29
|
+
dotnet format # 格式化代码
|
|
30
|
+
dotnet build /p:TreatWarningsAsErrors=true # 严格检查
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 命名约定
|
|
36
|
+
|
|
37
|
+
| 类型 | 规则 | 示例 |
|
|
38
|
+
|------|------|------|
|
|
39
|
+
| 命名空间 | PascalCase,公司.产品.模块 | `MyCompany.Project.Services` |
|
|
40
|
+
| 类/接口 | PascalCase,名词/名词短语 | `UserService`, `IUserRepository` |
|
|
41
|
+
| 方法名 | PascalCase,动词开头 | `FindById`, `IsValid` |
|
|
42
|
+
| 常量 | PascalCase | `MaxRetryCount` |
|
|
43
|
+
| 私有字段 | _camelCase 前缀下划线 | `_userRepository` |
|
|
44
|
+
| 布尔属性 | Is/Has/Can 前缀 | `IsActive`, `HasPermission` |
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 类成员顺序
|
|
49
|
+
|
|
50
|
+
```csharp
|
|
51
|
+
public class Example
|
|
52
|
+
{
|
|
53
|
+
// 1. 常量
|
|
54
|
+
public const string DefaultName = "value";
|
|
55
|
+
|
|
56
|
+
// 2. 静态字段
|
|
57
|
+
private static readonly ILogger<Example> _logger;
|
|
58
|
+
|
|
59
|
+
// 3. 实例字段
|
|
60
|
+
private readonly IUserRepository _userRepository;
|
|
61
|
+
private long _id;
|
|
62
|
+
|
|
63
|
+
// 4. 构造函数
|
|
64
|
+
public Example(IUserRepository userRepository)
|
|
65
|
+
{
|
|
66
|
+
_userRepository = userRepository;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 5. 属性
|
|
70
|
+
public long Id { get; set; }
|
|
71
|
+
|
|
72
|
+
// 6. 公共方法
|
|
73
|
+
public void DoSomething() { }
|
|
74
|
+
|
|
75
|
+
// 7. 私有方法
|
|
76
|
+
private void HelperMethod() { }
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 异常处理
|
|
83
|
+
|
|
84
|
+
```csharp
|
|
85
|
+
// ✅ 好:捕获具体异常,添加上下文
|
|
86
|
+
try
|
|
87
|
+
{
|
|
88
|
+
user = await _userRepository.FindByIdAsync(id);
|
|
89
|
+
}
|
|
90
|
+
catch (DbException ex)
|
|
91
|
+
{
|
|
92
|
+
throw new ServiceException($"Failed to find user: {id}", ex);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ✅ 好:资源自动释放
|
|
96
|
+
await using var stream = File.OpenRead(filePath);
|
|
97
|
+
|
|
98
|
+
// ❌ 差:捕获过宽
|
|
99
|
+
catch (Exception ex) { Console.WriteLine(ex); }
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 空值处理
|
|
105
|
+
|
|
106
|
+
```csharp
|
|
107
|
+
// ✅ 使用 Nullable Reference Types
|
|
108
|
+
public User? FindById(long id)
|
|
109
|
+
{
|
|
110
|
+
return _userRepository.FindById(id);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ✅ 参数校验
|
|
114
|
+
public void UpdateUser(User user)
|
|
115
|
+
{
|
|
116
|
+
ArgumentNullException.ThrowIfNull(user);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ✅ 安全的空值处理
|
|
120
|
+
var name = user?.Name ?? "Unknown";
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 异步编程
|
|
126
|
+
|
|
127
|
+
```csharp
|
|
128
|
+
// ✅ 使用 async/await
|
|
129
|
+
public async Task<User> GetUserAsync(long id)
|
|
130
|
+
{
|
|
131
|
+
return await _userRepository.FindByIdAsync(id);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ✅ 并行执行
|
|
135
|
+
var tasks = userIds.Select(id => GetUserAsync(id));
|
|
136
|
+
var users = await Task.WhenAll(tasks);
|
|
137
|
+
|
|
138
|
+
// ❌ 差:阻塞异步调用
|
|
139
|
+
var user = GetUserAsync(id).Result; // 可能死锁
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 测试规范 (xUnit)
|
|
145
|
+
|
|
146
|
+
```csharp
|
|
147
|
+
public class UserServiceTests
|
|
148
|
+
{
|
|
149
|
+
[Fact]
|
|
150
|
+
public async Task FindById_WhenUserExists_ReturnsUser()
|
|
151
|
+
{
|
|
152
|
+
// Arrange
|
|
153
|
+
var mockRepo = new Mock<IUserRepository>();
|
|
154
|
+
mockRepo.Setup(r => r.FindByIdAsync(1L))
|
|
155
|
+
.ReturnsAsync(new User { Id = 1, Name = "test" });
|
|
156
|
+
var service = new UserService(mockRepo.Object);
|
|
157
|
+
|
|
158
|
+
// Act
|
|
159
|
+
var result = await service.FindByIdAsync(1L);
|
|
160
|
+
|
|
161
|
+
// Assert
|
|
162
|
+
Assert.NotNull(result);
|
|
163
|
+
Assert.Equal("test", result.Name);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Furion 框架规范
|
|
171
|
+
|
|
172
|
+
```csharp
|
|
173
|
+
// ✅ 动态 API(自动生成路由)
|
|
174
|
+
[DynamicApiController]
|
|
175
|
+
public class UserService : IDynamicApiController
|
|
176
|
+
{
|
|
177
|
+
private readonly ISqlSugarRepository<User> _repository;
|
|
178
|
+
|
|
179
|
+
public UserService(ISqlSugarRepository<User> repository)
|
|
180
|
+
{
|
|
181
|
+
_repository = repository;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// GET /api/user/{id}
|
|
185
|
+
public async Task<User> GetAsync(long id)
|
|
186
|
+
{
|
|
187
|
+
return await _repository.GetByIdAsync(id);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// POST /api/user
|
|
191
|
+
public async Task<long> AddAsync(UserDto dto)
|
|
192
|
+
{
|
|
193
|
+
var user = dto.Adapt<User>();
|
|
194
|
+
return await _repository.InsertReturnIdentityAsync(user);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ✅ 传统 Controller(需要更多控制时)
|
|
199
|
+
[ApiController]
|
|
200
|
+
[Route("api/[controller]")]
|
|
201
|
+
public class UsersController : ControllerBase
|
|
202
|
+
{
|
|
203
|
+
[HttpGet("{id}")]
|
|
204
|
+
public async Task<ActionResult<UserDto>> GetById(long id)
|
|
205
|
+
{
|
|
206
|
+
var user = await _userService.GetAsync(id);
|
|
207
|
+
return user is null ? NotFound() : Ok(user);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## 性能优化
|
|
215
|
+
|
|
216
|
+
| 陷阱 | 解决方案 |
|
|
217
|
+
|------|---------|
|
|
218
|
+
| N+1 查询 | 使用 Includes() 或导航属性 |
|
|
219
|
+
| 循环拼接字符串 | 使用 `StringBuilder` |
|
|
220
|
+
| 频繁装箱拆箱 | 使用泛型集合 |
|
|
221
|
+
| 未使用异步 IO | 使用 async/await |
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## 日志规范
|
|
226
|
+
|
|
227
|
+
```csharp
|
|
228
|
+
// ✅ 结构化日志
|
|
229
|
+
_logger.LogDebug("Finding user by id: {UserId}", userId);
|
|
230
|
+
_logger.LogInformation("User {Username} logged in", username);
|
|
231
|
+
_logger.LogError(exception, "Failed to process order {OrderId}", orderId);
|
|
232
|
+
|
|
233
|
+
// ❌ 差:字符串拼接
|
|
234
|
+
_logger.LogDebug("Finding user by id: " + userId);
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 详细参考
|
|
240
|
+
|
|
241
|
+
完整规范见 `references/dotnet-style.md`,包含:
|
|
242
|
+
- 完整命名约定和示例
|
|
243
|
+
- 详细异常处理模式
|
|
244
|
+
- Furion 动态 API 最佳实践
|
|
245
|
+
- 异步编程详解
|
|
246
|
+
- SqlSugar ORM 使用
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
> 📋 本回复遵循:`dotnet-dev` - [具体章节]
|