--- name: dev-coding description: 软件编码开发技能。用于代码编写、功能实现、代码审查、重构优化。集成 ai-proj CLI 进行任务管理和进度跟踪。支持 Go、Vue、React、iOS、Android、小程序等全栈开发。 --- # 软件编码开发 Skill (dev-coding) ## ⚠️ REQ 任务自动工作流 **当收到 REQ 任务(包含 REQ-YYYYMMDD-XXXX)需要开发时,必须严格按以下顺序执行:** 1. **读取 ticket** — 从 ai-proj 获取需求详情和关联文档 ``` mcp__ai-proj-dev__get_detailed_task_info (通过 REQ 号查找) mcp__ai-proj-dev__get_task_document (如果有 PRD 文档) ``` 2. **进入 Plan Mode** — 调用 `EnterPlanMode` 工具 - 分析需求,探索代码库,设计实现方案 - 输出实现计划(涉及的文件、改动范围、测试策略) - 等待用户审批后再开始编码 3. **执行计划** — 用户批准后按计划编码 + 写测试 **禁止跳过 plan mode 直接编码。** --- ## 概述 本技能用于软件编码开发工作,支持多种项目类型: - Go 后端 (Gin + GORM) - Vue 3 / React 前端 - iOS (Swift/SwiftUI) - Android (Kotlin/Jetpack Compose) - PDA 应用 - MCP 桥接服务 - 微服务架构 核心集成 **ai-proj CLI** 进行任务管理。 --- ## ai-proj 任务管理 ### 开发任务工作流 ``` 1. 查看/创建任务 → 2. 启动任务 → 3. 编码实现 → 4. 完成任务 → 5. 记录文档 ``` ### 任务操作速查 | 操作 | CLI 命令 | 说明 | |------|----------|------| | 查看任务列表 | `ai-proj task list` | 查看项目所有任务 | | 创建任务 | `ai-proj task create` | 创建新任务 | | 创建子任务 | `ai-proj task create --parent-id` | 分解任务 | | 启动任务 | `ai-proj task start --id` | 开始执行 | | 完成任务 | `ai-proj task complete --id` | 标记完成 | | 更新任务 | `ai-proj task update --id` | 更新状态/描述 | | 查看详情 | `ai-proj task get --id` | 完整任务信息 | | 记录文档 | `ai-proj task append-doc --id` | 附加文档 | ### 开始新任务 ```bash # 1. 查看任务列表 ai-proj task list --status todo,in_progress # 2. 启动任务 ai-proj task start --id # 3. 完成后 ai-proj task complete --id # 4. 记录文档 ai-proj task append-doc --id --content "实现说明" ``` --- ## 项目类型速查 ### 当前项目生态 | 项目 | 类型 | 后端 | 前端 | 移动端 | |------|------|------|------|--------| | TWMS | 仓储物流 | Go+Gin+MySQL | Vue 3 | - | | AI-Proj | 项目管理 | Go+Gin+PostgreSQL | React 18 | iOS+Android | | DICIAI | 进销存SaaS | Go+Gin+MySQL | Vue 3 | Android PDA | --- ## Go 后端开发 ### 分层架构 ``` backend/ ├── cmd/main.go # 入口点 ├── internal/ │ ├── controller/handlers/ # HTTP 处理层 │ ├── biz/services/ # 业务逻辑层 │ ├── store/database/ # 数据访问层 │ └── middleware/ # 中间件 ├── pkg/ │ ├── model/ # 数据模型 │ ├── errno/ # 错误定义 │ ├── api/ # API 类型 │ └── util/ # 工具函数 └── configs/migrations/ # 配置和迁移 ``` ### 代码规范 ```go // 包声明和导入组织 package main import ( // 标准库 "context" "fmt" // 第三方 "github.com/gin-gonic/gin" // 项目内部 "project/internal/pkg/errno" ) // 错误处理 (Errno 模式) if err != nil { core.WriteResponse(c, errno.ErrBind, nil) return } // 接口定义 type IStore interface { Users() UserStore } // 服务注入 type userBiz struct { ds store.IStore } func NewUserBiz(ds store.IStore) *userBiz { return &userBiz{ds: ds} } ``` ### 常用命令 ```bash # 构建 make build go build -o ./_output/main ./cmd/main.go # 运行 ./_output/main --config ./configs/config.yaml # 测试 make test go test -v ./... # 代码检查 make lint golangci-lint run # Swagger 文档 make swagger swag init -g cmd/main.go ``` ### 数据库模型 ```go type UserM struct { Id int64 `gorm:"column:id;primary_key"` Username string `gorm:"column:username;not null"` CreateTime int64 `gorm:"column:create_time"` UpdateTime int64 `gorm:"column:update_time"` DeletedAt soft_delete.DeletedAt `gorm:"column:deleted_at"` } func (m *UserM) TableName() string { return "users" } func (m *UserM) BeforeCreate(tx *gorm.DB) error { m.CreateTime = time.Now().Unix() m.UpdateTime = m.CreateTime return nil } ``` --- ## 前端 data-testid 规范 编写或修改前端组件时,**所有可交互元素必须加 `data-testid`**。 **命名格式:** `<模块>-<元素类型>[-<标识>]` ```vue 创建商品 创建商品 ``` **必须加:** 输入框、选择器、开关、按钮(提交/取消/删除)、表格、模态框确认按钮、导航菜单项 **不需要加:** 纯展示文本、图标、布局容器(Row/Col/Space) --- ## Vue 3 前端开发 ### 项目结构 ``` frontend/src/ ├── api/ # API 服务 (按模块分组) │ ├── wms/ # 仓储管理 │ ├── oms/ # 订单管理 │ └── system/ # 系统管理 ├── views/ # 页面组件 ├── components/ # 可复用组件 ├── store/modules/ # Pinia 状态 ├── router/ # 路由配置 ├── utils/ │ ├── request.ts # Axios 拦截器 │ └── permission.ts # 权限检查 └── i18n/ # 国际化 ``` ### 代码规范 ```typescript // API 服务层 // api/user/model/index.ts export interface User { id: number; username: string; } // api/user/index.ts import request from '@/utils/request'; import type { ApiResult, PageResult } from '@/api'; import type { User } from './model'; export async function getUsers(params: UserParams) { const res = await request.get>>( '/v1/users', { params } ); if (res.status === 200) { return res.data; } return Promise.reject(new Error(res.data.message)); } ``` ### 常用命令 ```bash # 安装依赖 npm install pnpm install # DICIAI 使用 pnpm # 开发 npm run dev # 构建 npm run build:prod npm run build:test # 代码检查 npm run lint:eslint ``` --- ## React 前端开发 ### 项目结构 ``` frontend/src/ ├── pages/ # 页面组件 ├── components/ # 可复用组件 ├── services/ # API 服务 ├── hooks/ # 自定义 Hooks ├── contexts/ # Context Providers ├── types/ # TypeScript 类型 ├── utils/ # 工具函数 └── config/ # 配置 ``` ### 代码规范 ```typescript // Context 集成 // API 服务 const api = axios.create({ baseURL: API_BASE_URL, timeout: 120000, }); api.interceptors.request.use((config) => { const token = TokenManager.getToken(); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); ``` ### 常用命令 ```bash # 开发 npm start # 构建 npm run build # 测试 npm test npm run test:e2e ``` --- ## iOS 开发 (Swift/SwiftUI) ### 项目结构 ``` AI-Proj-iOS/ ├── Core/ # 核心服务 │ ├── Network/ # 网络层 │ ├── Storage/ # 本地存储 │ └── Auth/ # 认证 ├── Features/ # 功能模块 │ ├── Dashboard/ │ ├── Tasks/ │ └── Settings/ ├── Models/ # 数据模型 └── UI/ # UI 组件 ``` ### 代码规范 ```swift // MVVM 架构 class TaskViewModel: ObservableObject { @Published var tasks: [Task] = [] @Published var isLoading = false private let taskService: TaskServiceProtocol init(taskService: TaskServiceProtocol = TaskService()) { self.taskService = taskService } func fetchTasks() async { isLoading = true defer { isLoading = false } do { tasks = try await taskService.getTasks() } catch { // 错误处理 } } } // SwiftUI 视图 struct TaskListView: View { @StateObject private var viewModel = TaskViewModel() var body: some View { List(viewModel.tasks) { task in TaskRow(task: task) } .task { await viewModel.fetchTasks() } } } ``` ### 构建命令 ```bash # Xcode 构建 xcodebuild -scheme AI-Proj-iOS -configuration Debug # 测试 xcodebuild test -scheme AI-Proj-iOS ``` ### 常见问题排查 #### SwiftLint 沙盒错误 **问题描述**: 构建时出现错误: ``` Sandbox: swiftlint(xxxx) deny(1) file-read-data /path/to/.swiftlint.yml ``` **原因**: Xcode 15+ 默认启用 User Script Sandboxing,限制脚本访问文件系统。 **解决方案**: 方案 1 - 修改项目配置(推荐): 1. 打开 Xcode → 选择项目 → Build Settings 2. 搜索 "User Script Sandboxing" 3. 将 `ENABLE_USER_SCRIPT_SANDBOXING` 设置为 `NO` 方案 2 - 命令行构建时禁用: ```bash xcodebuild -scheme AI-Proj-iOS -configuration Debug \ ENABLE_USER_SCRIPT_SANDBOXING=NO ``` 方案 3 - 直接修改 project.pbxproj: ```bash sed -i '' 's/ENABLE_USER_SCRIPT_SANDBOXING = YES/ENABLE_USER_SCRIPT_SANDBOXING = NO/g' \ AI-Proj-iOS.xcodeproj/project.pbxproj ``` #### Personal Development Team 功能限制 **问题描述**: 使用免费 Personal Team 签名时报错: ``` Cannot create iOS App Development provisioning profile... Personal development teams do not support the Associated Domains, Push Notifications and App Groups capabilities. ``` **原因**: Personal Team(免费账户)不支持以下 Entitlements: - Associated Domains (`com.apple.developer.associated-domains`) - Push Notifications (`aps-environment`) - App Groups (`com.apple.security.application-groups`) **解决方案**: 1. 从 Entitlements 文件中移除不支持的功能: ```xml keychain-access-groups $(AppIdentifierPrefix)com.yourcompany.app ``` 2. Personal Team 支持的功能: - Keychain Access Groups ✓ - In-App Purchase ✓ - Game Center ✓ 3. 需要付费 Apple Developer Program 的功能: - Push Notifications ✗ - Associated Domains ✗ - App Groups ✗ - CloudKit ✗ - Sign in with Apple ✗ --- ## Android 开发 (Kotlin) ### 项目结构 ``` android-app/app/src/main/ ├── java/com/project/ │ ├── ui/ # UI 层 │ │ ├── screens/ # Compose 屏幕 │ │ └── components/ # 可复用组件 │ ├── data/ # 数据层 │ │ ├── api/ # 网络接口 │ │ ├── repository/ # 仓库模式 │ │ └── local/ # 本地存储 │ ├── domain/ # 业务逻辑 │ └── di/ # 依赖注入 └── res/ # 资源文件 ``` ### 代码规范 ```kotlin // Hilt 依赖注入 @HiltViewModel class TaskViewModel @Inject constructor( private val taskRepository: TaskRepository ) : ViewModel() { private val _tasks = MutableStateFlow>(emptyList()) val tasks: StateFlow> = _tasks.asStateFlow() fun fetchTasks() { viewModelScope.launch { taskRepository.getTasks() .collect { _tasks.value = it } } } } // Jetpack Compose @Composable fun TaskListScreen( viewModel: TaskViewModel = hiltViewModel() ) { val tasks by viewModel.tasks.collectAsState() LazyColumn { items(tasks) { task -> TaskItem(task = task) } } } ``` ### 构建命令 ```bash # 构建 Debug ./gradlew assembleDebug # 构建 Release ./gradlew assembleRelease # 测试 ./gradlew test ``` --- ## PDA 应用开发 ### 特点 - Android 原生开发 - 扫码枪集成 - 离线优先 - 简洁 UI ### 常见功能 ```kotlin // 扫码处理 class ScanReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val barcode = intent.getStringExtra("SCAN_BARCODE") // 处理扫码结果 } } // 离线存储 @Entity(tableName = "inventory") data class Inventory( @PrimaryKey val id: Long, val barcode: String, val quantity: Int, @ColumnInfo(name = "sync_status") val syncStatus: SyncStatus = SyncStatus.PENDING ) ``` --- ## MCP 桥接开发 ### 项目结构 ``` mcp-task-bridge/ ├── index.ts # 入口 ├── task-service.ts # 任务服务 ├── document-service.ts # 文档服务 ├── base-client.ts # HTTP 基类 ├── types.ts # 类型定义 └── token-storage.ts # Token 管理 ``` ### 代码规范 ```typescript // 服务类模式 export class TaskService extends BaseClient { async createTask( title: string, projectId: number = 1, options: CreateTaskOptions = {} ): Promise> { try { const response = await this.makeRequest( 'POST', `/projects/${projectId}/tasks`, { title, project_id: projectId, ...options } ); if (response.success) { return { success: true, data: response.data, message: `✅ 任务 "${title}" 创建成功` }; } return response; } catch (error: any) { return { success: false, error: `创建任务失败: ${error.message}` }; } } } ``` --- ## 通用开发规范 ### API 响应格式 ```json { "code": 0, "message": "success", "data": {} } ``` ### 分页参数 ```json { "page": 1, "limit": 20, "sort": "created_at", "order": "desc" } ``` ### 认证方式 - JWT Token - Header: `Authorization: Bearer ` ### 错误处理 ```go // Go if err != nil { core.WriteResponse(c, errno.ErrXxx, nil) return } // TypeScript try { const result = await api.call(); } catch (error) { message.error(error.message); } // Swift do { let result = try await service.fetch() } catch { // 处理错误 } ``` --- ## Git 工作流 ### 提交规范 | 类型 | 说明 | |------|------| | feat | 新功能 | | fix | Bug 修复 | | docs | 文档 | | refactor | 重构 | | test | 测试 | | chore | 杂项 | ### 双电脑同步 (au-dev / cn-dev) ```bash # 离开时 git add -A git commit -m "WIP: sync from $(hostname)" git push origin $(git branch --show-current) # 到达时 git fetch origin git pull origin $(git branch --show-current) ``` --- ## Docker 部署 ### 标准配置 ```yaml # docker-compose.yml services: backend: build: ./backend ports: - "8080:8080" depends_on: - db - redis frontend: build: ./frontend ports: - "80:80" db: image: mysql:8.0 # 或 postgres:15 redis: image: redis:alpine ``` ### 常用端口 | 服务 | 端口 | |------|------| | Backend | 8080 / 9099 | | Frontend | 80 / 3000 | | MySQL | 3306 | | PostgreSQL | 5432 | | Redis | 6379 | --- ## Push 前必须通过:变更包单元测试 **在 `git push` 或 `/pr create` 之前,必须跑所有变更文件对应包的单元测试。** ```bash # 找出变更的 Go 文件所在包,跑对应测试 PKGS=$(git diff --name-only origin/main...HEAD | grep '\.go$' | grep -v '_test\.go' | sed 's|/[^/]*$||' | sort -u | sed 's|^|./|' | tr '\n' ' ') if [ -n "$PKGS" ]; then echo "Running tests for changed packages: $PKGS" go test -v -count=1 $PKGS else echo "No Go files changed, skipping tests" fi ``` **规则:** - 测试通过 → 继续 push + `/pr create` - 测试失败 → 尝试自动修复,修复后重跑 - 修复成功 → 继续 push - **修复失败 → 禁止 push,向用户报告失败原因,等待指示** - 仅改了 `_test.go` → 同样需要跑(验证测试本身通过) - 无 Go 文件变更(纯前端/文档) → 跳过 --- ## 最佳实践 1. **任务驱动** - 使用 ai-proj 管理所有开发任务 2. **分层清晰** - Controller → Service → Repository 3. **接口先行** - 先定义接口再实现 4. **小步提交** - 频繁提交,每次做一件事 5. **测试覆盖** - 核心逻辑必须有测试 6. **文档同步** - 代码变更同步更新文档 ## 相关技能 | 技能 | 用途 | 关系 | |------|------|------| | `req-test-gate` | 测试与质量门禁 + Harness Engineering | 建立项目质量门禁和约定自动检测,dev-coding 遵守其建立的 CLAUDE.md 约定 |