Files
aiops/docs/development-guide.md
T
LoganandClaude 76ec9387f0 feat(rdp): 新增 RDP 远程桌面/SMB/账单同步能力 + 清理编译产物
主要变更:
- RDP 远程桌面:新增 backend/pkg/rdp(RDP 引擎 + credssp/display/rle/trace)、
  backend/controller/rdp*(连接/凭证/文件/会话/实时)、frontend RDP 组件与 API
- Windows SMB 文件传输:backend/pkg/winsmb
- 云账单同步:backend/pkg/billingsync + billing_sync/aliyun_billing,前端账单详情
- Agent CLI Kubernetes 工具:kubernetes_action/get、pod_execute/logs
- 服务器导入助手:server_import_helpers、ImportCredentialSettings
- 国际化与组件重构(cloud/deploy/monitor/server/system 等多模块)
- 清理编译产物二进制:移除 backend/server、backend/agent/bin/aiops-agent-*
- .gitignore:新增 backend/agent/ 与 .cache/(避免 334MB go-build 缓存误入库)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-04 01:50:36 +08:00

266 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 开发规范
## Git 工作流
### 分支策略
| 分支 | 说明 |
|------|------|
| `main` / `master` | 生产分支,保护分支 |
| `dev` | 开发集成分支 |
| `feature/*` | 功能分支 |
| `fix/*` | 修复分支 |
| `hotfix/*` | 紧急修复 |
### 提交规范
```
<type>: <description>
- 变更点 1
- 变更点 2
```
Type 列表:
- `feat`: 新功能
- `fix`: Bug 修复
- `refactor`: 重构
- `docs`: 文档
- `style`: 样式
- `test`: 测试
- `chore`: 构建/工具
示例:
```
feat: 添加服务器批量导入功能
- 支持 Excel 导入
- 支持云平台同步
```
## 后端规范(Go)
### 目录职责
| 目录 | 职责 |
|------|------|
| `main.go` / `embed.go` | 应用入口 + 前端嵌入 |
| `controller/` | HTTP 请求处理(参数校验、响应) |
| `model/` | 数据模型定义 |
| `config/` | 配置管理 (Viper) |
| `middleware/` | JWT / 日志 / CORS 中间件 |
| `router/` | 路由注册 |
| `service/` / `repository/` | 业务逻辑 / 数据访问 |
| `pkg/database/` | 数据库连接 + AutoMigrate |
| `pkg/agentcli/` | Agent CLI 引擎(ReAct + Evolver) |
| `pkg/remoteexec/` | Go-native SSH 远程执行 |
| `static/` | 前端 embed 静态资源 |
### 命名规范
- 文件名:`snake_case.go`
- 类型/方法:`PascalCase`
- 变量:`camelCase`
- 常量:`PascalCase` 或 `ALL_CAPS`
### 统一响应格式
```go
// 成功响应
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
Data: result,
})
// 分页响应
c.JSON(http.StatusOK, models.Response{
Code: 200,
Message: "success",
Data: models.ListResponse{
List: items,
Total: total,
},
})
// 错误响应
c.JSON(http.StatusBadRequest, models.Response{
Code: 400,
Message: "参数错误: " + err.Error(),
})
```
### Handler 模板
```go
func (h *ServerHandler) CreateServer(c *gin.Context) {
// 1. 参数绑定
var req models.ServerRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: err.Error()})
return
}
// 2. 业务逻辑
server := models.Server{
Name: req.Name,
IP: req.IP,
}
if err := h.db.Create(&server).Error; err != nil {
c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: "创建失败"})
return
}
// 3. 返回结果
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "创建成功", Data: server})
}
```
### 注意事项
- GORM `First()` 连续查询会带上次 ID,用 `Take()` 代替
- Go 编译前设置 `GOPROXY=https://goproxy.cn,direct`
- SQLite 需要 `CGO_ENABLED=1`
- JWT 使用 `golang-jwt/jwt/v5`,`jwt.TimeFunc()` 已移除,用 `time.Now()`
- 新增或修改代码注释末尾署名 `// Logan.Li`
## 前端规范(React + TypeScript)
### 目录职责
| 目录 | 职责 |
|------|------|
| `src/api/` | API 封装(按菜单域分子目录,`http.ts` 自动解包 `.data`) |
| `src/pages/` | 复杂域级页面(多 Tab / 多子面板) |
| `src/components/*/` | 可复用业务组件 |
| `src/components/layout/` | PageShell / Sidebar / Header / ThemePicker |
| `src/components/ui/` | shadcn/ui 基础组件 |
| `src/locales/` | i18n 翻译文件(zh-CN.json / en-US.json) |
| `src/i18n/` | i18next 初始化 |
| `src/hooks/` | 自定义 Hooks |
| `src/store/` | Zustand 状态管理 |
| `src/types/` | TypeScript 类型(按域拆分) |
| `src/utils/` | 主题 / 权限 / 导出等工具 |
### 命名规范
- 组件文件:`PascalCase.tsx`(如 `ServerManager.tsx`)
- 工具文件:`camelCase.ts`(如 `formatDate.ts`)
- 组件名:`PascalCase`
### PageShell 页面骨架
新页面优先使用 `PageShell` 统一布局:
```tsx
import { PageShell } from '@/components/layout/PageShell';
import { useTranslation } from 'react-i18next';
export function MyPage() {
const { t } = useTranslation();
return (
<PageShell
title={t('myModule.title')}
subtitle={t('myModule.subtitle')}
icon={<ServerIcon className="h-5 w-5" />}
actions={<Button>操作</Button>}
toolbar={<SearchInput />}
tabs={[{ id: 'list', label: t('myModule.tabList') }]}
activeTab="list"
onTabChange={() => {}}
variant="list"
>
{/* 页面内容 */}
</PageShell>
);
}
```
`variant` 取值:`default` | `list` | `config` | `workspace`。
### 国际化 (i18n)
- 框架:i18next + react-i18next
- 语言:`zh-CN`(默认)/ `en-US`
- 翻译文件:`src/locales/zh-CN.json` / `en-US.json`
- 命名空间按模块划分:`common`、`menu`、`dashboard`、`server`、`alert`、`approval`、`audit`、`deploy`、`k8s` 等
新增文案规范:
```tsx
// ✅ 使用翻译键
const { t } = useTranslation();
<span>{t('server.batchImport')}</span>
// ❌ 禁止硬编码中文(已迁移模块)
<span>批量导入</span>
```
双语同步:修改 `zh-CN.json` 时必须同步更新 `en-US.json`。
### UI 设计原则
- 能去掉的装饰都去掉(无边框、无多余分隔线)
- 选中态用 `bg-surface-active`,不用彩色高亮
- 页面打开即用,不需要额外的"新建"按钮跳转
- 主题感知 — 使用 CSS 变量 `var(--dg-xxx)`,不硬编码颜色
- 按钮文案 2–4 字
- 禁止 `window.confirm()` / `alert()`,使用 `useConfirm()` + `toast`
- Radix Dialog 必须包含 `<DialogDescription>`
### API 调用
前端通过 Vite 代理访问后端 API:
```typescript
// 开发环境请求会被代理到 http://localhost:8080
// http.ts 已自动提取 Response.Data,列表返回 { list, total }
import { getServers } from '@/api/server';
const { list, total } = await getServers({ page: 1 });
```
## 测试
### 后端测试
```bash
cd backend
go vet ./...
go build -o aiops .
```
### 前端构建测试
```bash
cd frontend
npm run build
npx tsc --noEmit # 类型检查(提交前零错误)
```
### 独立二进制构建
```bash
./run.sh build tag v1.5.0
./aiops version
```
### 集成测试
```bash
python3 tests/integration_test.py --host localhost --port 8080
```
## 日志
| 级别 | 使用场景 |
|------|---------|
| Info | 服务启动、正常操作 |
| Warn | 配置缺失、降级处理 |
| Error | 操作失败、异常 |
| Fatal | 启动失败、不可恢复 |
```go
log.Info("server started", zap.String("port", cfg.Port))
log.Error("database error", zap.Error(err))
```